xref: /onnv-gate/usr/src/common/openssl/crypto/pkcs7/pk7_doit.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/pkcs7/pk7_doit.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate #include <stdio.h>
600Sstevel@tonic-gate #include "cryptlib.h"
610Sstevel@tonic-gate #include <openssl/rand.h>
620Sstevel@tonic-gate #include <openssl/objects.h>
630Sstevel@tonic-gate #include <openssl/x509.h>
640Sstevel@tonic-gate #include <openssl/x509v3.h>
65*2139Sjp161948 #include <openssl/err.h>
660Sstevel@tonic-gate 
670Sstevel@tonic-gate static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
680Sstevel@tonic-gate 			 void *value);
690Sstevel@tonic-gate static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
700Sstevel@tonic-gate 
PKCS7_type_is_other(PKCS7 * p7)710Sstevel@tonic-gate static int PKCS7_type_is_other(PKCS7* p7)
720Sstevel@tonic-gate 	{
730Sstevel@tonic-gate 	int isOther=1;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	int nid=OBJ_obj2nid(p7->type);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	switch( nid )
780Sstevel@tonic-gate 		{
790Sstevel@tonic-gate 	case NID_pkcs7_data:
800Sstevel@tonic-gate 	case NID_pkcs7_signed:
810Sstevel@tonic-gate 	case NID_pkcs7_enveloped:
820Sstevel@tonic-gate 	case NID_pkcs7_signedAndEnveloped:
830Sstevel@tonic-gate 	case NID_pkcs7_digest:
840Sstevel@tonic-gate 	case NID_pkcs7_encrypted:
850Sstevel@tonic-gate 		isOther=0;
860Sstevel@tonic-gate 		break;
870Sstevel@tonic-gate 	default:
880Sstevel@tonic-gate 		isOther=1;
890Sstevel@tonic-gate 		}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	return isOther;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	}
940Sstevel@tonic-gate 
PKCS7_get_octet_string(PKCS7 * p7)950Sstevel@tonic-gate static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
960Sstevel@tonic-gate 	{
970Sstevel@tonic-gate 	if ( PKCS7_type_is_data(p7))
980Sstevel@tonic-gate 		return p7->d.data;
990Sstevel@tonic-gate 	if ( PKCS7_type_is_other(p7) && p7->d.other
1000Sstevel@tonic-gate 		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
1010Sstevel@tonic-gate 		return p7->d.other->value.octet_string;
1020Sstevel@tonic-gate 	return NULL;
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 
PKCS7_bio_add_digest(BIO ** pbio,X509_ALGOR * alg)105*2139Sjp161948 static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
106*2139Sjp161948 	{
107*2139Sjp161948 	BIO *btmp;
108*2139Sjp161948 	const EVP_MD *md;
109*2139Sjp161948 	if ((btmp=BIO_new(BIO_f_md())) == NULL)
110*2139Sjp161948 		{
111*2139Sjp161948 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
112*2139Sjp161948 		goto err;
113*2139Sjp161948 		}
114*2139Sjp161948 
115*2139Sjp161948 	md=EVP_get_digestbyobj(alg->algorithm);
116*2139Sjp161948 	if (md == NULL)
117*2139Sjp161948 		{
118*2139Sjp161948 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
119*2139Sjp161948 		goto err;
120*2139Sjp161948 		}
121*2139Sjp161948 
122*2139Sjp161948 	BIO_set_md(btmp,md);
123*2139Sjp161948 	if (*pbio == NULL)
124*2139Sjp161948 		*pbio=btmp;
125*2139Sjp161948 	else if (!BIO_push(*pbio,btmp))
126*2139Sjp161948 		{
127*2139Sjp161948 		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
128*2139Sjp161948 		goto err;
129*2139Sjp161948 		}
130*2139Sjp161948 	btmp=NULL;
131*2139Sjp161948 
132*2139Sjp161948 	return 1;
133*2139Sjp161948 
134*2139Sjp161948 	err:
135*2139Sjp161948 	if (btmp)
136*2139Sjp161948 		BIO_free(btmp);
137*2139Sjp161948 	return 0;
138*2139Sjp161948 
139*2139Sjp161948 	}
140*2139Sjp161948 
PKCS7_dataInit(PKCS7 * p7,BIO * bio)1410Sstevel@tonic-gate BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
1420Sstevel@tonic-gate 	{
1430Sstevel@tonic-gate 	int i;
1440Sstevel@tonic-gate 	BIO *out=NULL,*btmp=NULL;
145*2139Sjp161948 	X509_ALGOR *xa = NULL;
1460Sstevel@tonic-gate 	const EVP_CIPHER *evp_cipher=NULL;
1470Sstevel@tonic-gate 	STACK_OF(X509_ALGOR) *md_sk=NULL;
1480Sstevel@tonic-gate 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
1490Sstevel@tonic-gate 	X509_ALGOR *xalg=NULL;
1500Sstevel@tonic-gate 	PKCS7_RECIP_INFO *ri=NULL;
1510Sstevel@tonic-gate 	EVP_PKEY *pkey;
152*2139Sjp161948 	ASN1_OCTET_STRING *os=NULL;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	i=OBJ_obj2nid(p7->type);
1550Sstevel@tonic-gate 	p7->state=PKCS7_S_HEADER;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	switch (i)
1580Sstevel@tonic-gate 		{
1590Sstevel@tonic-gate 	case NID_pkcs7_signed:
1600Sstevel@tonic-gate 		md_sk=p7->d.sign->md_algs;
161*2139Sjp161948 		os = PKCS7_get_octet_string(p7->d.sign->contents);
1620Sstevel@tonic-gate 		break;
1630Sstevel@tonic-gate 	case NID_pkcs7_signedAndEnveloped:
1640Sstevel@tonic-gate 		rsk=p7->d.signed_and_enveloped->recipientinfo;
1650Sstevel@tonic-gate 		md_sk=p7->d.signed_and_enveloped->md_algs;
1660Sstevel@tonic-gate 		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
1670Sstevel@tonic-gate 		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
1680Sstevel@tonic-gate 		if (evp_cipher == NULL)
1690Sstevel@tonic-gate 			{
1700Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
1710Sstevel@tonic-gate 						PKCS7_R_CIPHER_NOT_INITIALIZED);
1720Sstevel@tonic-gate 			goto err;
1730Sstevel@tonic-gate 			}
1740Sstevel@tonic-gate 		break;
1750Sstevel@tonic-gate 	case NID_pkcs7_enveloped:
1760Sstevel@tonic-gate 		rsk=p7->d.enveloped->recipientinfo;
1770Sstevel@tonic-gate 		xalg=p7->d.enveloped->enc_data->algorithm;
1780Sstevel@tonic-gate 		evp_cipher=p7->d.enveloped->enc_data->cipher;
1790Sstevel@tonic-gate 		if (evp_cipher == NULL)
1800Sstevel@tonic-gate 			{
1810Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
1820Sstevel@tonic-gate 						PKCS7_R_CIPHER_NOT_INITIALIZED);
1830Sstevel@tonic-gate 			goto err;
1840Sstevel@tonic-gate 			}
1850Sstevel@tonic-gate 		break;
186*2139Sjp161948 	case NID_pkcs7_digest:
187*2139Sjp161948 		xa = p7->d.digest->md;
188*2139Sjp161948 		os = PKCS7_get_octet_string(p7->d.digest->contents);
189*2139Sjp161948 		break;
1900Sstevel@tonic-gate 	default:
1910Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
1920Sstevel@tonic-gate 	        goto err;
1930Sstevel@tonic-gate 		}
1940Sstevel@tonic-gate 
195*2139Sjp161948 	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
196*2139Sjp161948 		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
197*2139Sjp161948 			goto err;
1980Sstevel@tonic-gate 
199*2139Sjp161948 	if (xa && !PKCS7_bio_add_digest(&out, xa))
200*2139Sjp161948 			goto err;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	if (evp_cipher != NULL)
2030Sstevel@tonic-gate 		{
2040Sstevel@tonic-gate 		unsigned char key[EVP_MAX_KEY_LENGTH];
2050Sstevel@tonic-gate 		unsigned char iv[EVP_MAX_IV_LENGTH];
2060Sstevel@tonic-gate 		int keylen,ivlen;
2070Sstevel@tonic-gate 		int jj,max;
2080Sstevel@tonic-gate 		unsigned char *tmp;
2090Sstevel@tonic-gate 		EVP_CIPHER_CTX *ctx;
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
2120Sstevel@tonic-gate 			{
2130Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
2140Sstevel@tonic-gate 			goto err;
2150Sstevel@tonic-gate 			}
2160Sstevel@tonic-gate 		BIO_get_cipher_ctx(btmp, &ctx);
2170Sstevel@tonic-gate 		keylen=EVP_CIPHER_key_length(evp_cipher);
2180Sstevel@tonic-gate 		ivlen=EVP_CIPHER_iv_length(evp_cipher);
2190Sstevel@tonic-gate 		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
2200Sstevel@tonic-gate 		if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
221*2139Sjp161948 		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
222*2139Sjp161948 			goto err;
223*2139Sjp161948 		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
224*2139Sjp161948 			goto err;
225*2139Sjp161948 		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
226*2139Sjp161948 			goto err;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 		if (ivlen > 0) {
2290Sstevel@tonic-gate 			if (xalg->parameter == NULL)
2300Sstevel@tonic-gate 						xalg->parameter=ASN1_TYPE_new();
2310Sstevel@tonic-gate 			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
2320Sstevel@tonic-gate 								       goto err;
2330Sstevel@tonic-gate 		}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 		/* Lets do the pub key stuff :-) */
2360Sstevel@tonic-gate 		max=0;
2370Sstevel@tonic-gate 		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
2380Sstevel@tonic-gate 			{
2390Sstevel@tonic-gate 			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
2400Sstevel@tonic-gate 			if (ri->cert == NULL)
2410Sstevel@tonic-gate 				{
2420Sstevel@tonic-gate 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
2430Sstevel@tonic-gate 				goto err;
2440Sstevel@tonic-gate 				}
2450Sstevel@tonic-gate 			pkey=X509_get_pubkey(ri->cert);
2460Sstevel@tonic-gate 			jj=EVP_PKEY_size(pkey);
2470Sstevel@tonic-gate 			EVP_PKEY_free(pkey);
2480Sstevel@tonic-gate 			if (max < jj) max=jj;
2490Sstevel@tonic-gate 			}
2500Sstevel@tonic-gate 		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
2510Sstevel@tonic-gate 			{
2520Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
2530Sstevel@tonic-gate 			goto err;
2540Sstevel@tonic-gate 			}
2550Sstevel@tonic-gate 		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
2560Sstevel@tonic-gate 			{
2570Sstevel@tonic-gate 			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
2580Sstevel@tonic-gate 			pkey=X509_get_pubkey(ri->cert);
2590Sstevel@tonic-gate 			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
2600Sstevel@tonic-gate 			EVP_PKEY_free(pkey);
2610Sstevel@tonic-gate 			if (jj <= 0)
2620Sstevel@tonic-gate 				{
2630Sstevel@tonic-gate 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
2640Sstevel@tonic-gate 				OPENSSL_free(tmp);
2650Sstevel@tonic-gate 				goto err;
2660Sstevel@tonic-gate 				}
267*2139Sjp161948 			if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
268*2139Sjp161948 				{
269*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATAINIT,
270*2139Sjp161948 					ERR_R_MALLOC_FAILURE);
271*2139Sjp161948 				OPENSSL_free(tmp);
272*2139Sjp161948 				goto err;
273*2139Sjp161948 				}
2740Sstevel@tonic-gate 			}
2750Sstevel@tonic-gate 		OPENSSL_free(tmp);
2760Sstevel@tonic-gate 		OPENSSL_cleanse(key, keylen);
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 		if (out == NULL)
2790Sstevel@tonic-gate 			out=btmp;
2800Sstevel@tonic-gate 		else
2810Sstevel@tonic-gate 			BIO_push(out,btmp);
2820Sstevel@tonic-gate 		btmp=NULL;
2830Sstevel@tonic-gate 		}
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (bio == NULL)
2860Sstevel@tonic-gate 		{
2870Sstevel@tonic-gate 		if (PKCS7_is_detached(p7))
2880Sstevel@tonic-gate 			bio=BIO_new(BIO_s_null());
289*2139Sjp161948 		else if (os && os->length > 0)
290*2139Sjp161948 			bio = BIO_new_mem_buf(os->data, os->length);
291*2139Sjp161948 		if(bio == NULL)
2920Sstevel@tonic-gate 			{
293*2139Sjp161948 			bio=BIO_new(BIO_s_mem());
294*2139Sjp161948 			BIO_set_mem_eof_return(bio,0);
2950Sstevel@tonic-gate 			}
296*2139Sjp161948 		}
2970Sstevel@tonic-gate 	BIO_push(out,bio);
2980Sstevel@tonic-gate 	bio=NULL;
2990Sstevel@tonic-gate 	if (0)
3000Sstevel@tonic-gate 		{
3010Sstevel@tonic-gate err:
3020Sstevel@tonic-gate 		if (out != NULL)
3030Sstevel@tonic-gate 			BIO_free_all(out);
3040Sstevel@tonic-gate 		if (btmp != NULL)
3050Sstevel@tonic-gate 			BIO_free_all(btmp);
3060Sstevel@tonic-gate 		out=NULL;
3070Sstevel@tonic-gate 		}
3080Sstevel@tonic-gate 	return(out);
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate 
pkcs7_cmp_ri(PKCS7_RECIP_INFO * ri,X509 * pcert)311*2139Sjp161948 static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
312*2139Sjp161948 	{
313*2139Sjp161948 	int ret;
314*2139Sjp161948 	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
315*2139Sjp161948 				pcert->cert_info->issuer);
316*2139Sjp161948 	if (ret)
317*2139Sjp161948 		return ret;
318*2139Sjp161948 	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
319*2139Sjp161948 					ri->issuer_and_serial->serial);
320*2139Sjp161948 	}
321*2139Sjp161948 
3220Sstevel@tonic-gate /* int */
PKCS7_dataDecode(PKCS7 * p7,EVP_PKEY * pkey,BIO * in_bio,X509 * pcert)3230Sstevel@tonic-gate BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
3240Sstevel@tonic-gate 	{
3250Sstevel@tonic-gate 	int i,j;
3260Sstevel@tonic-gate 	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
3270Sstevel@tonic-gate 	unsigned char *tmp=NULL;
3280Sstevel@tonic-gate 	X509_ALGOR *xa;
3290Sstevel@tonic-gate 	ASN1_OCTET_STRING *data_body=NULL;
3300Sstevel@tonic-gate 	const EVP_MD *evp_md;
3310Sstevel@tonic-gate 	const EVP_CIPHER *evp_cipher=NULL;
3320Sstevel@tonic-gate 	EVP_CIPHER_CTX *evp_ctx=NULL;
3330Sstevel@tonic-gate 	X509_ALGOR *enc_alg=NULL;
3340Sstevel@tonic-gate 	STACK_OF(X509_ALGOR) *md_sk=NULL;
3350Sstevel@tonic-gate 	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
3360Sstevel@tonic-gate 	X509_ALGOR *xalg=NULL;
3370Sstevel@tonic-gate 	PKCS7_RECIP_INFO *ri=NULL;
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	i=OBJ_obj2nid(p7->type);
3400Sstevel@tonic-gate 	p7->state=PKCS7_S_HEADER;
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 	switch (i)
3430Sstevel@tonic-gate 		{
3440Sstevel@tonic-gate 	case NID_pkcs7_signed:
3450Sstevel@tonic-gate 		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
3460Sstevel@tonic-gate 		md_sk=p7->d.sign->md_algs;
3470Sstevel@tonic-gate 		break;
3480Sstevel@tonic-gate 	case NID_pkcs7_signedAndEnveloped:
3490Sstevel@tonic-gate 		rsk=p7->d.signed_and_enveloped->recipientinfo;
3500Sstevel@tonic-gate 		md_sk=p7->d.signed_and_enveloped->md_algs;
3510Sstevel@tonic-gate 		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
3520Sstevel@tonic-gate 		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
3530Sstevel@tonic-gate 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
3540Sstevel@tonic-gate 		if (evp_cipher == NULL)
3550Sstevel@tonic-gate 			{
3560Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
3570Sstevel@tonic-gate 			goto err;
3580Sstevel@tonic-gate 			}
3590Sstevel@tonic-gate 		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
3600Sstevel@tonic-gate 		break;
3610Sstevel@tonic-gate 	case NID_pkcs7_enveloped:
3620Sstevel@tonic-gate 		rsk=p7->d.enveloped->recipientinfo;
3630Sstevel@tonic-gate 		enc_alg=p7->d.enveloped->enc_data->algorithm;
3640Sstevel@tonic-gate 		data_body=p7->d.enveloped->enc_data->enc_data;
3650Sstevel@tonic-gate 		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
3660Sstevel@tonic-gate 		if (evp_cipher == NULL)
3670Sstevel@tonic-gate 			{
3680Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
3690Sstevel@tonic-gate 			goto err;
3700Sstevel@tonic-gate 			}
3710Sstevel@tonic-gate 		xalg=p7->d.enveloped->enc_data->algorithm;
3720Sstevel@tonic-gate 		break;
3730Sstevel@tonic-gate 	default:
3740Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
3750Sstevel@tonic-gate 	        goto err;
3760Sstevel@tonic-gate 		}
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/* We will be checking the signature */
3790Sstevel@tonic-gate 	if (md_sk != NULL)
3800Sstevel@tonic-gate 		{
3810Sstevel@tonic-gate 		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
3820Sstevel@tonic-gate 			{
3830Sstevel@tonic-gate 			xa=sk_X509_ALGOR_value(md_sk,i);
3840Sstevel@tonic-gate 			if ((btmp=BIO_new(BIO_f_md())) == NULL)
3850Sstevel@tonic-gate 				{
3860Sstevel@tonic-gate 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
3870Sstevel@tonic-gate 				goto err;
3880Sstevel@tonic-gate 				}
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 			j=OBJ_obj2nid(xa->algorithm);
3910Sstevel@tonic-gate 			evp_md=EVP_get_digestbynid(j);
3920Sstevel@tonic-gate 			if (evp_md == NULL)
3930Sstevel@tonic-gate 				{
3940Sstevel@tonic-gate 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
3950Sstevel@tonic-gate 				goto err;
3960Sstevel@tonic-gate 				}
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 			BIO_set_md(btmp,evp_md);
3990Sstevel@tonic-gate 			if (out == NULL)
4000Sstevel@tonic-gate 				out=btmp;
4010Sstevel@tonic-gate 			else
4020Sstevel@tonic-gate 				BIO_push(out,btmp);
4030Sstevel@tonic-gate 			btmp=NULL;
4040Sstevel@tonic-gate 			}
4050Sstevel@tonic-gate 		}
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	if (evp_cipher != NULL)
4080Sstevel@tonic-gate 		{
4090Sstevel@tonic-gate #if 0
4100Sstevel@tonic-gate 		unsigned char key[EVP_MAX_KEY_LENGTH];
4110Sstevel@tonic-gate 		unsigned char iv[EVP_MAX_IV_LENGTH];
4120Sstevel@tonic-gate 		unsigned char *p;
4130Sstevel@tonic-gate 		int keylen,ivlen;
4140Sstevel@tonic-gate 		int max;
4150Sstevel@tonic-gate 		X509_OBJECT ret;
4160Sstevel@tonic-gate #endif
4170Sstevel@tonic-gate 		int jj;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
4200Sstevel@tonic-gate 			{
4210Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
4220Sstevel@tonic-gate 			goto err;
4230Sstevel@tonic-gate 			}
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 		/* It was encrypted, we need to decrypt the secret key
4260Sstevel@tonic-gate 		 * with the private key */
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 		/* Find the recipientInfo which matches the passed certificate
4290Sstevel@tonic-gate 		 * (if any)
4300Sstevel@tonic-gate 		 */
4310Sstevel@tonic-gate 
432*2139Sjp161948 		if (pcert) {
433*2139Sjp161948 			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
434*2139Sjp161948 				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
435*2139Sjp161948 				if (!pkcs7_cmp_ri(ri, pcert))
436*2139Sjp161948 					break;
437*2139Sjp161948 				ri=NULL;
438*2139Sjp161948 			}
439*2139Sjp161948 			if (ri == NULL) {
440*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
441*2139Sjp161948 				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
442*2139Sjp161948 				goto err;
443*2139Sjp161948 			}
4440Sstevel@tonic-gate 		}
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 		jj=EVP_PKEY_size(pkey);
4470Sstevel@tonic-gate 		tmp=(unsigned char *)OPENSSL_malloc(jj+10);
4480Sstevel@tonic-gate 		if (tmp == NULL)
4490Sstevel@tonic-gate 			{
4500Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
4510Sstevel@tonic-gate 			goto err;
4520Sstevel@tonic-gate 			}
4530Sstevel@tonic-gate 
454*2139Sjp161948 		/* If we haven't got a certificate try each ri in turn */
455*2139Sjp161948 
456*2139Sjp161948 		if (pcert == NULL)
4570Sstevel@tonic-gate 			{
458*2139Sjp161948 			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
459*2139Sjp161948 				{
460*2139Sjp161948 				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
461*2139Sjp161948 				jj=EVP_PKEY_decrypt(tmp,
462*2139Sjp161948 					M_ASN1_STRING_data(ri->enc_key),
463*2139Sjp161948 					M_ASN1_STRING_length(ri->enc_key),
464*2139Sjp161948 						pkey);
465*2139Sjp161948 				if (jj > 0)
466*2139Sjp161948 					break;
467*2139Sjp161948 				ERR_clear_error();
468*2139Sjp161948 				ri = NULL;
469*2139Sjp161948 				}
470*2139Sjp161948 			if (ri == NULL)
471*2139Sjp161948 				{
472*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
473*2139Sjp161948 				      PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
474*2139Sjp161948 				goto err;
475*2139Sjp161948 				}
476*2139Sjp161948 			}
477*2139Sjp161948 		else
478*2139Sjp161948 			{
479*2139Sjp161948 			jj=EVP_PKEY_decrypt(tmp,
480*2139Sjp161948 				M_ASN1_STRING_data(ri->enc_key),
481*2139Sjp161948 				M_ASN1_STRING_length(ri->enc_key), pkey);
482*2139Sjp161948 			if (jj <= 0)
483*2139Sjp161948 				{
484*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
485*2139Sjp161948 								ERR_R_EVP_LIB);
486*2139Sjp161948 				goto err;
487*2139Sjp161948 				}
4880Sstevel@tonic-gate 			}
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 		evp_ctx=NULL;
4910Sstevel@tonic-gate 		BIO_get_cipher_ctx(etmp,&evp_ctx);
492*2139Sjp161948 		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
493*2139Sjp161948 			goto err;
4940Sstevel@tonic-gate 		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
4950Sstevel@tonic-gate 			goto err;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
4980Sstevel@tonic-gate 			/* Some S/MIME clients don't use the same key
4990Sstevel@tonic-gate 			 * and effective key length. The key length is
5000Sstevel@tonic-gate 			 * determined by the size of the decrypted RSA key.
5010Sstevel@tonic-gate 			 */
5020Sstevel@tonic-gate 			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
5030Sstevel@tonic-gate 				{
5040Sstevel@tonic-gate 				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
5050Sstevel@tonic-gate 					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
5060Sstevel@tonic-gate 				goto err;
5070Sstevel@tonic-gate 				}
5080Sstevel@tonic-gate 		}
509*2139Sjp161948 		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
510*2139Sjp161948 			goto err;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 		OPENSSL_cleanse(tmp,jj);
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 		if (out == NULL)
5150Sstevel@tonic-gate 			out=etmp;
5160Sstevel@tonic-gate 		else
5170Sstevel@tonic-gate 			BIO_push(out,etmp);
5180Sstevel@tonic-gate 		etmp=NULL;
5190Sstevel@tonic-gate 		}
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate #if 1
5220Sstevel@tonic-gate 	if (PKCS7_is_detached(p7) || (in_bio != NULL))
5230Sstevel@tonic-gate 		{
5240Sstevel@tonic-gate 		bio=in_bio;
5250Sstevel@tonic-gate 		}
5260Sstevel@tonic-gate 	else
5270Sstevel@tonic-gate 		{
5280Sstevel@tonic-gate #if 0
5290Sstevel@tonic-gate 		bio=BIO_new(BIO_s_mem());
5300Sstevel@tonic-gate 		/* We need to set this so that when we have read all
5310Sstevel@tonic-gate 		 * the data, the encrypt BIO, if present, will read
5320Sstevel@tonic-gate 		 * EOF and encode the last few bytes */
5330Sstevel@tonic-gate 		BIO_set_mem_eof_return(bio,0);
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 		if (data_body->length > 0)
5360Sstevel@tonic-gate 			BIO_write(bio,(char *)data_body->data,data_body->length);
5370Sstevel@tonic-gate #else
5380Sstevel@tonic-gate 		if (data_body->length > 0)
5390Sstevel@tonic-gate 		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
5400Sstevel@tonic-gate 		else {
5410Sstevel@tonic-gate 			bio=BIO_new(BIO_s_mem());
5420Sstevel@tonic-gate 			BIO_set_mem_eof_return(bio,0);
5430Sstevel@tonic-gate 		}
5440Sstevel@tonic-gate #endif
5450Sstevel@tonic-gate 		}
5460Sstevel@tonic-gate 	BIO_push(out,bio);
5470Sstevel@tonic-gate 	bio=NULL;
5480Sstevel@tonic-gate #endif
5490Sstevel@tonic-gate 	if (0)
5500Sstevel@tonic-gate 		{
5510Sstevel@tonic-gate err:
5520Sstevel@tonic-gate 		if (out != NULL) BIO_free_all(out);
5530Sstevel@tonic-gate 		if (btmp != NULL) BIO_free_all(btmp);
5540Sstevel@tonic-gate 		if (etmp != NULL) BIO_free_all(etmp);
5550Sstevel@tonic-gate 		if (bio != NULL) BIO_free_all(bio);
5560Sstevel@tonic-gate 		out=NULL;
5570Sstevel@tonic-gate 		}
5580Sstevel@tonic-gate 	if (tmp != NULL)
5590Sstevel@tonic-gate 		OPENSSL_free(tmp);
5600Sstevel@tonic-gate 	return(out);
5610Sstevel@tonic-gate 	}
5620Sstevel@tonic-gate 
PKCS7_find_digest(EVP_MD_CTX ** pmd,BIO * bio,int nid)563*2139Sjp161948 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
564*2139Sjp161948 	{
565*2139Sjp161948 	for (;;)
566*2139Sjp161948 		{
567*2139Sjp161948 		bio=BIO_find_type(bio,BIO_TYPE_MD);
568*2139Sjp161948 		if (bio == NULL)
569*2139Sjp161948 			{
570*2139Sjp161948 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
571*2139Sjp161948 			return NULL;
572*2139Sjp161948 			}
573*2139Sjp161948 		BIO_get_md_ctx(bio,pmd);
574*2139Sjp161948 		if (*pmd == NULL)
575*2139Sjp161948 			{
576*2139Sjp161948 			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
577*2139Sjp161948 			return NULL;
578*2139Sjp161948 			}
579*2139Sjp161948 		if (EVP_MD_CTX_type(*pmd) == nid)
580*2139Sjp161948 			return bio;
581*2139Sjp161948 		bio=BIO_next(bio);
582*2139Sjp161948 		}
583*2139Sjp161948 	return NULL;
584*2139Sjp161948 	}
585*2139Sjp161948 
PKCS7_dataFinal(PKCS7 * p7,BIO * bio)5860Sstevel@tonic-gate int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
5870Sstevel@tonic-gate 	{
5880Sstevel@tonic-gate 	int ret=0;
5890Sstevel@tonic-gate 	int i,j;
5900Sstevel@tonic-gate 	BIO *btmp;
5910Sstevel@tonic-gate 	BUF_MEM *buf_mem=NULL;
5920Sstevel@tonic-gate 	BUF_MEM *buf=NULL;
5930Sstevel@tonic-gate 	PKCS7_SIGNER_INFO *si;
5940Sstevel@tonic-gate 	EVP_MD_CTX *mdc,ctx_tmp;
5950Sstevel@tonic-gate 	STACK_OF(X509_ATTRIBUTE) *sk;
5960Sstevel@tonic-gate 	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
5970Sstevel@tonic-gate 	ASN1_OCTET_STRING *os=NULL;
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	EVP_MD_CTX_init(&ctx_tmp);
6000Sstevel@tonic-gate 	i=OBJ_obj2nid(p7->type);
6010Sstevel@tonic-gate 	p7->state=PKCS7_S_HEADER;
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate 	switch (i)
6040Sstevel@tonic-gate 		{
6050Sstevel@tonic-gate 	case NID_pkcs7_signedAndEnveloped:
6060Sstevel@tonic-gate 		/* XXXXXXXXXXXXXXXX */
6070Sstevel@tonic-gate 		si_sk=p7->d.signed_and_enveloped->signer_info;
608*2139Sjp161948 		if (!(os=M_ASN1_OCTET_STRING_new()))
609*2139Sjp161948 			{
610*2139Sjp161948 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
611*2139Sjp161948 			goto err;
612*2139Sjp161948 			}
6130Sstevel@tonic-gate 		p7->d.signed_and_enveloped->enc_data->enc_data=os;
6140Sstevel@tonic-gate 		break;
6150Sstevel@tonic-gate 	case NID_pkcs7_enveloped:
6160Sstevel@tonic-gate 		/* XXXXXXXXXXXXXXXX */
617*2139Sjp161948 		if (!(os=M_ASN1_OCTET_STRING_new()))
618*2139Sjp161948 			{
619*2139Sjp161948 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
620*2139Sjp161948 			goto err;
621*2139Sjp161948 			}
6220Sstevel@tonic-gate 		p7->d.enveloped->enc_data->enc_data=os;
6230Sstevel@tonic-gate 		break;
6240Sstevel@tonic-gate 	case NID_pkcs7_signed:
6250Sstevel@tonic-gate 		si_sk=p7->d.sign->signer_info;
6260Sstevel@tonic-gate 		os=PKCS7_get_octet_string(p7->d.sign->contents);
6270Sstevel@tonic-gate 		/* If detached data then the content is excluded */
6280Sstevel@tonic-gate 		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
6290Sstevel@tonic-gate 			M_ASN1_OCTET_STRING_free(os);
6300Sstevel@tonic-gate 			p7->d.sign->contents->d.data = NULL;
6310Sstevel@tonic-gate 		}
6320Sstevel@tonic-gate 		break;
633*2139Sjp161948 
634*2139Sjp161948 	case NID_pkcs7_digest:
635*2139Sjp161948 		os=PKCS7_get_octet_string(p7->d.digest->contents);
636*2139Sjp161948 		/* If detached data then the content is excluded */
637*2139Sjp161948 		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
638*2139Sjp161948 			{
639*2139Sjp161948 			M_ASN1_OCTET_STRING_free(os);
640*2139Sjp161948 			p7->d.digest->contents->d.data = NULL;
641*2139Sjp161948 			}
642*2139Sjp161948 		break;
643*2139Sjp161948 
6440Sstevel@tonic-gate 		}
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	if (si_sk != NULL)
6470Sstevel@tonic-gate 		{
6480Sstevel@tonic-gate 		if ((buf=BUF_MEM_new()) == NULL)
6490Sstevel@tonic-gate 			{
650*2139Sjp161948 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
6510Sstevel@tonic-gate 			goto err;
6520Sstevel@tonic-gate 			}
6530Sstevel@tonic-gate 		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
6540Sstevel@tonic-gate 			{
6550Sstevel@tonic-gate 			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
6560Sstevel@tonic-gate 			if (si->pkey == NULL) continue;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 			j=OBJ_obj2nid(si->digest_alg->algorithm);
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 			btmp=bio;
661*2139Sjp161948 
662*2139Sjp161948 			btmp = PKCS7_find_digest(&mdc, btmp, j);
663*2139Sjp161948 
664*2139Sjp161948 			if (btmp == NULL)
665*2139Sjp161948 				goto err;
666*2139Sjp161948 
6670Sstevel@tonic-gate 			/* We now have the EVP_MD_CTX, lets do the
6680Sstevel@tonic-gate 			 * signing. */
6690Sstevel@tonic-gate 			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
6700Sstevel@tonic-gate 			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
6710Sstevel@tonic-gate 				{
672*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
6730Sstevel@tonic-gate 				goto err;
6740Sstevel@tonic-gate 				}
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 			sk=si->auth_attr;
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 			/* If there are attributes, we add the digest
6790Sstevel@tonic-gate 			 * attribute and only sign the attributes */
6800Sstevel@tonic-gate 			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
6810Sstevel@tonic-gate 				{
6820Sstevel@tonic-gate 				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
6830Sstevel@tonic-gate 				unsigned int md_len, alen;
6840Sstevel@tonic-gate 				ASN1_OCTET_STRING *digest;
6850Sstevel@tonic-gate 				ASN1_UTCTIME *sign_time;
6860Sstevel@tonic-gate 				const EVP_MD *md_tmp;
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate 				/* Add signing time if not already present */
6890Sstevel@tonic-gate 				if (!PKCS7_get_signed_attribute(si,
6900Sstevel@tonic-gate 							NID_pkcs9_signingTime))
6910Sstevel@tonic-gate 					{
692*2139Sjp161948 					if (!(sign_time=X509_gmtime_adj(NULL,0)))
693*2139Sjp161948 						{
694*2139Sjp161948 						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
695*2139Sjp161948 							ERR_R_MALLOC_FAILURE);
696*2139Sjp161948 						goto err;
697*2139Sjp161948 						}
6980Sstevel@tonic-gate 					PKCS7_add_signed_attribute(si,
6990Sstevel@tonic-gate 						NID_pkcs9_signingTime,
7000Sstevel@tonic-gate 						V_ASN1_UTCTIME,sign_time);
7010Sstevel@tonic-gate 					}
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 				/* Add digest */
7040Sstevel@tonic-gate 				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
7050Sstevel@tonic-gate 				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
706*2139Sjp161948 				if (!(digest=M_ASN1_OCTET_STRING_new()))
707*2139Sjp161948 					{
708*2139Sjp161948 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
709*2139Sjp161948 						ERR_R_MALLOC_FAILURE);
710*2139Sjp161948 					goto err;
711*2139Sjp161948 					}
712*2139Sjp161948 				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
713*2139Sjp161948 								md_len))
714*2139Sjp161948 					{
715*2139Sjp161948 					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
716*2139Sjp161948 						ERR_R_MALLOC_FAILURE);
717*2139Sjp161948 					goto err;
718*2139Sjp161948 					}
7190Sstevel@tonic-gate 				PKCS7_add_signed_attribute(si,
7200Sstevel@tonic-gate 					NID_pkcs9_messageDigest,
7210Sstevel@tonic-gate 					V_ASN1_OCTET_STRING,digest);
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 				/* Now sign the attributes */
7240Sstevel@tonic-gate 				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
7250Sstevel@tonic-gate 				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
7260Sstevel@tonic-gate 							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
7270Sstevel@tonic-gate 				if(!abuf) goto err;
7280Sstevel@tonic-gate 				EVP_SignUpdate(&ctx_tmp,abuf,alen);
7290Sstevel@tonic-gate 				OPENSSL_free(abuf);
7300Sstevel@tonic-gate 				}
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
7330Sstevel@tonic-gate 			if (si->pkey->type == EVP_PKEY_DSA)
7340Sstevel@tonic-gate 				ctx_tmp.digest=EVP_dss1();
7350Sstevel@tonic-gate #endif
736*2139Sjp161948 #ifndef OPENSSL_NO_ECDSA
737*2139Sjp161948  			if (si->pkey->type == EVP_PKEY_EC)
738*2139Sjp161948  				ctx_tmp.digest=EVP_ecdsa();
739*2139Sjp161948 #endif
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
7420Sstevel@tonic-gate 				(unsigned int *)&buf->length,si->pkey))
7430Sstevel@tonic-gate 				{
744*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
7450Sstevel@tonic-gate 				goto err;
7460Sstevel@tonic-gate 				}
7470Sstevel@tonic-gate 			if (!ASN1_STRING_set(si->enc_digest,
7480Sstevel@tonic-gate 				(unsigned char *)buf->data,buf->length))
7490Sstevel@tonic-gate 				{
750*2139Sjp161948 				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
7510Sstevel@tonic-gate 				goto err;
7520Sstevel@tonic-gate 				}
7530Sstevel@tonic-gate 			}
7540Sstevel@tonic-gate 		}
755*2139Sjp161948 	else if (i == NID_pkcs7_digest)
756*2139Sjp161948 		{
757*2139Sjp161948 		unsigned char md_data[EVP_MAX_MD_SIZE];
758*2139Sjp161948 		unsigned int md_len;
759*2139Sjp161948 		if (!PKCS7_find_digest(&mdc, bio,
760*2139Sjp161948 				OBJ_obj2nid(p7->d.digest->md->algorithm)))
761*2139Sjp161948 			goto err;
762*2139Sjp161948 		EVP_DigestFinal_ex(mdc,md_data,&md_len);
763*2139Sjp161948 		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
764*2139Sjp161948 		}
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	if (!PKCS7_is_detached(p7))
7670Sstevel@tonic-gate 		{
7680Sstevel@tonic-gate 		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
7690Sstevel@tonic-gate 		if (btmp == NULL)
7700Sstevel@tonic-gate 			{
771*2139Sjp161948 			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
7720Sstevel@tonic-gate 			goto err;
7730Sstevel@tonic-gate 			}
7740Sstevel@tonic-gate 		BIO_get_mem_ptr(btmp,&buf_mem);
7750Sstevel@tonic-gate 		/* Mark the BIO read only then we can use its copy of the data
7760Sstevel@tonic-gate 		 * instead of making an extra copy.
7770Sstevel@tonic-gate 		 */
7780Sstevel@tonic-gate 		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
7790Sstevel@tonic-gate 		BIO_set_mem_eof_return(btmp, 0);
7800Sstevel@tonic-gate 		os->data = (unsigned char *)buf_mem->data;
7810Sstevel@tonic-gate 		os->length = buf_mem->length;
7820Sstevel@tonic-gate #if 0
7830Sstevel@tonic-gate 		M_ASN1_OCTET_STRING_set(os,
7840Sstevel@tonic-gate 			(unsigned char *)buf_mem->data,buf_mem->length);
7850Sstevel@tonic-gate #endif
7860Sstevel@tonic-gate 		}
7870Sstevel@tonic-gate 	ret=1;
7880Sstevel@tonic-gate err:
7890Sstevel@tonic-gate 	EVP_MD_CTX_cleanup(&ctx_tmp);
7900Sstevel@tonic-gate 	if (buf != NULL) BUF_MEM_free(buf);
7910Sstevel@tonic-gate 	return(ret);
7920Sstevel@tonic-gate 	}
7930Sstevel@tonic-gate 
PKCS7_dataVerify(X509_STORE * cert_store,X509_STORE_CTX * ctx,BIO * bio,PKCS7 * p7,PKCS7_SIGNER_INFO * si)7940Sstevel@tonic-gate int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
7950Sstevel@tonic-gate 	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
7960Sstevel@tonic-gate 	{
7970Sstevel@tonic-gate 	PKCS7_ISSUER_AND_SERIAL *ias;
7980Sstevel@tonic-gate 	int ret=0,i;
7990Sstevel@tonic-gate 	STACK_OF(X509) *cert;
8000Sstevel@tonic-gate 	X509 *x509;
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 	if (PKCS7_type_is_signed(p7))
8030Sstevel@tonic-gate 		{
8040Sstevel@tonic-gate 		cert=p7->d.sign->cert;
8050Sstevel@tonic-gate 		}
8060Sstevel@tonic-gate 	else if (PKCS7_type_is_signedAndEnveloped(p7))
8070Sstevel@tonic-gate 		{
8080Sstevel@tonic-gate 		cert=p7->d.signed_and_enveloped->cert;
8090Sstevel@tonic-gate 		}
8100Sstevel@tonic-gate 	else
8110Sstevel@tonic-gate 		{
8120Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
8130Sstevel@tonic-gate 		goto err;
8140Sstevel@tonic-gate 		}
8150Sstevel@tonic-gate 	/* XXXXXXXXXXXXXXXXXXXXXXX */
8160Sstevel@tonic-gate 	ias=si->issuer_and_serial;
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	/* were we able to find the cert in passed to us */
8210Sstevel@tonic-gate 	if (x509 == NULL)
8220Sstevel@tonic-gate 		{
8230Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
8240Sstevel@tonic-gate 		goto err;
8250Sstevel@tonic-gate 		}
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate 	/* Lets verify */
8280Sstevel@tonic-gate 	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
8290Sstevel@tonic-gate 		{
8300Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
8310Sstevel@tonic-gate 		goto err;
8320Sstevel@tonic-gate 		}
8330Sstevel@tonic-gate 	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
8340Sstevel@tonic-gate 	i=X509_verify_cert(ctx);
8350Sstevel@tonic-gate 	if (i <= 0)
8360Sstevel@tonic-gate 		{
8370Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
8380Sstevel@tonic-gate 		X509_STORE_CTX_cleanup(ctx);
8390Sstevel@tonic-gate 		goto err;
8400Sstevel@tonic-gate 		}
8410Sstevel@tonic-gate 	X509_STORE_CTX_cleanup(ctx);
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	return PKCS7_signatureVerify(bio, p7, si, x509);
8440Sstevel@tonic-gate 	err:
8450Sstevel@tonic-gate 	return ret;
8460Sstevel@tonic-gate 	}
8470Sstevel@tonic-gate 
PKCS7_signatureVerify(BIO * bio,PKCS7 * p7,PKCS7_SIGNER_INFO * si,X509 * x509)8480Sstevel@tonic-gate int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
8490Sstevel@tonic-gate 								X509 *x509)
8500Sstevel@tonic-gate 	{
8510Sstevel@tonic-gate 	ASN1_OCTET_STRING *os;
8520Sstevel@tonic-gate 	EVP_MD_CTX mdc_tmp,*mdc;
8530Sstevel@tonic-gate 	int ret=0,i;
8540Sstevel@tonic-gate 	int md_type;
8550Sstevel@tonic-gate 	STACK_OF(X509_ATTRIBUTE) *sk;
8560Sstevel@tonic-gate 	BIO *btmp;
8570Sstevel@tonic-gate 	EVP_PKEY *pkey;
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate 	EVP_MD_CTX_init(&mdc_tmp);
8600Sstevel@tonic-gate 
8610Sstevel@tonic-gate 	if (!PKCS7_type_is_signed(p7) &&
8620Sstevel@tonic-gate 				!PKCS7_type_is_signedAndEnveloped(p7)) {
8630Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
8640Sstevel@tonic-gate 						PKCS7_R_WRONG_PKCS7_TYPE);
8650Sstevel@tonic-gate 		goto err;
8660Sstevel@tonic-gate 	}
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	md_type=OBJ_obj2nid(si->digest_alg->algorithm);
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate 	btmp=bio;
8710Sstevel@tonic-gate 	for (;;)
8720Sstevel@tonic-gate 		{
8730Sstevel@tonic-gate 		if ((btmp == NULL) ||
8740Sstevel@tonic-gate 			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
8750Sstevel@tonic-gate 			{
8760Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
8770Sstevel@tonic-gate 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
8780Sstevel@tonic-gate 			goto err;
8790Sstevel@tonic-gate 			}
8800Sstevel@tonic-gate 		BIO_get_md_ctx(btmp,&mdc);
8810Sstevel@tonic-gate 		if (mdc == NULL)
8820Sstevel@tonic-gate 			{
8830Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
8840Sstevel@tonic-gate 							ERR_R_INTERNAL_ERROR);
8850Sstevel@tonic-gate 			goto err;
8860Sstevel@tonic-gate 			}
8870Sstevel@tonic-gate 		if (EVP_MD_CTX_type(mdc) == md_type)
8880Sstevel@tonic-gate 			break;
8890Sstevel@tonic-gate 		/* Workaround for some broken clients that put the signature
8900Sstevel@tonic-gate 		 * OID instead of the digest OID in digest_alg->algorithm
8910Sstevel@tonic-gate 		 */
8920Sstevel@tonic-gate 		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
8930Sstevel@tonic-gate 			break;
8940Sstevel@tonic-gate 		btmp=BIO_next(btmp);
8950Sstevel@tonic-gate 		}
8960Sstevel@tonic-gate 
8970Sstevel@tonic-gate 	/* mdc is the digest ctx that we want, unless there are attributes,
8980Sstevel@tonic-gate 	 * in which case the digest is the signed attributes */
8990Sstevel@tonic-gate 	EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	sk=si->auth_attr;
9020Sstevel@tonic-gate 	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
9030Sstevel@tonic-gate 		{
9040Sstevel@tonic-gate 		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
9050Sstevel@tonic-gate                 unsigned int md_len, alen;
9060Sstevel@tonic-gate 		ASN1_OCTET_STRING *message_digest;
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 		EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
9090Sstevel@tonic-gate 		message_digest=PKCS7_digest_from_attributes(sk);
9100Sstevel@tonic-gate 		if (!message_digest)
9110Sstevel@tonic-gate 			{
9120Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
9130Sstevel@tonic-gate 					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
9140Sstevel@tonic-gate 			goto err;
9150Sstevel@tonic-gate 			}
9160Sstevel@tonic-gate 		if ((message_digest->length != (int)md_len) ||
9170Sstevel@tonic-gate 			(memcmp(message_digest->data,md_dat,md_len)))
9180Sstevel@tonic-gate 			{
9190Sstevel@tonic-gate #if 0
9200Sstevel@tonic-gate {
9210Sstevel@tonic-gate int ii;
9220Sstevel@tonic-gate for (ii=0; ii<message_digest->length; ii++)
9230Sstevel@tonic-gate 	printf("%02X",message_digest->data[ii]); printf(" sent\n");
9240Sstevel@tonic-gate for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
9250Sstevel@tonic-gate }
9260Sstevel@tonic-gate #endif
9270Sstevel@tonic-gate 			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
9280Sstevel@tonic-gate 							PKCS7_R_DIGEST_FAILURE);
9290Sstevel@tonic-gate 			ret= -1;
9300Sstevel@tonic-gate 			goto err;
9310Sstevel@tonic-gate 			}
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate 		EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL);
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
9360Sstevel@tonic-gate 						ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
9370Sstevel@tonic-gate 		EVP_VerifyUpdate(&mdc_tmp, abuf, alen);
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 		OPENSSL_free(abuf);
9400Sstevel@tonic-gate 		}
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 	os=si->enc_digest;
9430Sstevel@tonic-gate 	pkey = X509_get_pubkey(x509);
9440Sstevel@tonic-gate 	if (!pkey)
9450Sstevel@tonic-gate 		{
9460Sstevel@tonic-gate 		ret = -1;
9470Sstevel@tonic-gate 		goto err;
9480Sstevel@tonic-gate 		}
9490Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
9500Sstevel@tonic-gate 	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
9510Sstevel@tonic-gate #endif
952*2139Sjp161948 #ifndef OPENSSL_NO_ECDSA
953*2139Sjp161948 	if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
954*2139Sjp161948 #endif
9550Sstevel@tonic-gate 
9560Sstevel@tonic-gate 	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
9570Sstevel@tonic-gate 	EVP_PKEY_free(pkey);
9580Sstevel@tonic-gate 	if (i <= 0)
9590Sstevel@tonic-gate 		{
9600Sstevel@tonic-gate 		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
9610Sstevel@tonic-gate 						PKCS7_R_SIGNATURE_FAILURE);
9620Sstevel@tonic-gate 		ret= -1;
9630Sstevel@tonic-gate 		goto err;
9640Sstevel@tonic-gate 		}
9650Sstevel@tonic-gate 	else
9660Sstevel@tonic-gate 		ret=1;
9670Sstevel@tonic-gate err:
9680Sstevel@tonic-gate 	EVP_MD_CTX_cleanup(&mdc_tmp);
9690Sstevel@tonic-gate 	return(ret);
9700Sstevel@tonic-gate 	}
9710Sstevel@tonic-gate 
PKCS7_get_issuer_and_serial(PKCS7 * p7,int idx)9720Sstevel@tonic-gate PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
9730Sstevel@tonic-gate 	{
9740Sstevel@tonic-gate 	STACK_OF(PKCS7_RECIP_INFO) *rsk;
9750Sstevel@tonic-gate 	PKCS7_RECIP_INFO *ri;
9760Sstevel@tonic-gate 	int i;
9770Sstevel@tonic-gate 
9780Sstevel@tonic-gate 	i=OBJ_obj2nid(p7->type);
9790Sstevel@tonic-gate 	if (i != NID_pkcs7_signedAndEnveloped) return(NULL);
9800Sstevel@tonic-gate 	rsk=p7->d.signed_and_enveloped->recipientinfo;
9810Sstevel@tonic-gate 	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
9820Sstevel@tonic-gate 	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
9830Sstevel@tonic-gate 	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
9840Sstevel@tonic-gate 	return(ri->issuer_and_serial);
9850Sstevel@tonic-gate 	}
9860Sstevel@tonic-gate 
PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO * si,int nid)9870Sstevel@tonic-gate ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
9880Sstevel@tonic-gate 	{
9890Sstevel@tonic-gate 	return(get_attribute(si->auth_attr,nid));
9900Sstevel@tonic-gate 	}
9910Sstevel@tonic-gate 
PKCS7_get_attribute(PKCS7_SIGNER_INFO * si,int nid)9920Sstevel@tonic-gate ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
9930Sstevel@tonic-gate 	{
9940Sstevel@tonic-gate 	return(get_attribute(si->unauth_attr,nid));
9950Sstevel@tonic-gate 	}
9960Sstevel@tonic-gate 
get_attribute(STACK_OF (X509_ATTRIBUTE)* sk,int nid)9970Sstevel@tonic-gate static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
9980Sstevel@tonic-gate 	{
9990Sstevel@tonic-gate 	int i;
10000Sstevel@tonic-gate 	X509_ATTRIBUTE *xa;
10010Sstevel@tonic-gate 	ASN1_OBJECT *o;
10020Sstevel@tonic-gate 
10030Sstevel@tonic-gate 	o=OBJ_nid2obj(nid);
10040Sstevel@tonic-gate 	if (!o || !sk) return(NULL);
10050Sstevel@tonic-gate 	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
10060Sstevel@tonic-gate 		{
10070Sstevel@tonic-gate 		xa=sk_X509_ATTRIBUTE_value(sk,i);
10080Sstevel@tonic-gate 		if (OBJ_cmp(xa->object,o) == 0)
10090Sstevel@tonic-gate 			{
10100Sstevel@tonic-gate 			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
10110Sstevel@tonic-gate 				return(sk_ASN1_TYPE_value(xa->value.set,0));
10120Sstevel@tonic-gate 			else
10130Sstevel@tonic-gate 				return(NULL);
10140Sstevel@tonic-gate 			}
10150Sstevel@tonic-gate 		}
10160Sstevel@tonic-gate 	return(NULL);
10170Sstevel@tonic-gate 	}
10180Sstevel@tonic-gate 
PKCS7_digest_from_attributes(STACK_OF (X509_ATTRIBUTE)* sk)10190Sstevel@tonic-gate ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
10200Sstevel@tonic-gate {
10210Sstevel@tonic-gate 	ASN1_TYPE *astype;
10220Sstevel@tonic-gate 	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
10230Sstevel@tonic-gate 	return astype->value.octet_string;
10240Sstevel@tonic-gate }
10250Sstevel@tonic-gate 
PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO * p7si,STACK_OF (X509_ATTRIBUTE)* sk)10260Sstevel@tonic-gate int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
10270Sstevel@tonic-gate 				STACK_OF(X509_ATTRIBUTE) *sk)
10280Sstevel@tonic-gate 	{
10290Sstevel@tonic-gate 	int i;
10300Sstevel@tonic-gate 
10310Sstevel@tonic-gate 	if (p7si->auth_attr != NULL)
10320Sstevel@tonic-gate 		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
10330Sstevel@tonic-gate 	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
10340Sstevel@tonic-gate 	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
10350Sstevel@tonic-gate 		{
10360Sstevel@tonic-gate 		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
10370Sstevel@tonic-gate 			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
10380Sstevel@tonic-gate 		    == NULL)
10390Sstevel@tonic-gate 			return(0);
10400Sstevel@tonic-gate 		}
10410Sstevel@tonic-gate 	return(1);
10420Sstevel@tonic-gate 	}
10430Sstevel@tonic-gate 
PKCS7_set_attributes(PKCS7_SIGNER_INFO * p7si,STACK_OF (X509_ATTRIBUTE)* sk)10440Sstevel@tonic-gate int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
10450Sstevel@tonic-gate 	{
10460Sstevel@tonic-gate 	int i;
10470Sstevel@tonic-gate 
10480Sstevel@tonic-gate 	if (p7si->unauth_attr != NULL)
10490Sstevel@tonic-gate 		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
10500Sstevel@tonic-gate 					   X509_ATTRIBUTE_free);
10510Sstevel@tonic-gate 	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
10520Sstevel@tonic-gate 	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
10530Sstevel@tonic-gate 		{
10540Sstevel@tonic-gate 		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
10550Sstevel@tonic-gate                         X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
10560Sstevel@tonic-gate 		    == NULL)
10570Sstevel@tonic-gate 			return(0);
10580Sstevel@tonic-gate 		}
10590Sstevel@tonic-gate 	return(1);
10600Sstevel@tonic-gate 	}
10610Sstevel@tonic-gate 
PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO * p7si,int nid,int atrtype,void * value)10620Sstevel@tonic-gate int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
10630Sstevel@tonic-gate 	     void *value)
10640Sstevel@tonic-gate 	{
10650Sstevel@tonic-gate 	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
10660Sstevel@tonic-gate 	}
10670Sstevel@tonic-gate 
PKCS7_add_attribute(PKCS7_SIGNER_INFO * p7si,int nid,int atrtype,void * value)10680Sstevel@tonic-gate int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
10690Sstevel@tonic-gate 	     void *value)
10700Sstevel@tonic-gate 	{
10710Sstevel@tonic-gate 	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
10720Sstevel@tonic-gate 	}
10730Sstevel@tonic-gate 
add_attribute(STACK_OF (X509_ATTRIBUTE)** sk,int nid,int atrtype,void * value)10740Sstevel@tonic-gate static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
10750Sstevel@tonic-gate 			 void *value)
10760Sstevel@tonic-gate 	{
10770Sstevel@tonic-gate 	X509_ATTRIBUTE *attr=NULL;
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 	if (*sk == NULL)
10800Sstevel@tonic-gate 		{
10810Sstevel@tonic-gate 		*sk = sk_X509_ATTRIBUTE_new_null();
10820Sstevel@tonic-gate new_attrib:
10830Sstevel@tonic-gate 		attr=X509_ATTRIBUTE_create(nid,atrtype,value);
10840Sstevel@tonic-gate 		sk_X509_ATTRIBUTE_push(*sk,attr);
10850Sstevel@tonic-gate 		}
10860Sstevel@tonic-gate 	else
10870Sstevel@tonic-gate 		{
10880Sstevel@tonic-gate 		int i;
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 		for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++)
10910Sstevel@tonic-gate 			{
10920Sstevel@tonic-gate 			attr=sk_X509_ATTRIBUTE_value(*sk,i);
10930Sstevel@tonic-gate 			if (OBJ_obj2nid(attr->object) == nid)
10940Sstevel@tonic-gate 				{
10950Sstevel@tonic-gate 				X509_ATTRIBUTE_free(attr);
10960Sstevel@tonic-gate 				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
10970Sstevel@tonic-gate 				sk_X509_ATTRIBUTE_set(*sk,i,attr);
10980Sstevel@tonic-gate 				goto end;
10990Sstevel@tonic-gate 				}
11000Sstevel@tonic-gate 			}
11010Sstevel@tonic-gate 		goto new_attrib;
11020Sstevel@tonic-gate 		}
11030Sstevel@tonic-gate end:
11040Sstevel@tonic-gate 	return(1);
11050Sstevel@tonic-gate 	}
11060Sstevel@tonic-gate 
1107