os/ossrv/ssl/libcrypto/src/crypto/pkcs7/pk7_doit.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/pkcs7/pk7_doit.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
sl@0
    59
#include <stdio.h>
sl@0
    60
#include "cryptlib.h"
sl@0
    61
#include <openssl/rand.h>
sl@0
    62
#include <openssl/objects.h>
sl@0
    63
#include <openssl/x509.h>
sl@0
    64
#include <openssl/x509v3.h>
sl@0
    65
#include <openssl/err.h>
sl@0
    66
sl@0
    67
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
sl@0
    68
			 void *value);
sl@0
    69
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
sl@0
    70
sl@0
    71
static int PKCS7_type_is_other(PKCS7* p7)
sl@0
    72
	{
sl@0
    73
	int isOther=1;
sl@0
    74
	
sl@0
    75
	int nid=OBJ_obj2nid(p7->type);
sl@0
    76
sl@0
    77
	switch( nid )
sl@0
    78
		{
sl@0
    79
	case NID_pkcs7_data:
sl@0
    80
	case NID_pkcs7_signed:
sl@0
    81
	case NID_pkcs7_enveloped:
sl@0
    82
	case NID_pkcs7_signedAndEnveloped:
sl@0
    83
	case NID_pkcs7_digest:
sl@0
    84
	case NID_pkcs7_encrypted:
sl@0
    85
		isOther=0;
sl@0
    86
		break;
sl@0
    87
	default:
sl@0
    88
		isOther=1;
sl@0
    89
		}
sl@0
    90
sl@0
    91
	return isOther;
sl@0
    92
sl@0
    93
	}
sl@0
    94
sl@0
    95
static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
sl@0
    96
	{
sl@0
    97
	if ( PKCS7_type_is_data(p7))
sl@0
    98
		return p7->d.data;
sl@0
    99
	if ( PKCS7_type_is_other(p7) && p7->d.other
sl@0
   100
		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
sl@0
   101
		return p7->d.other->value.octet_string;
sl@0
   102
	return NULL;
sl@0
   103
	}
sl@0
   104
sl@0
   105
static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
sl@0
   106
	{
sl@0
   107
	BIO *btmp;
sl@0
   108
	const EVP_MD *md;
sl@0
   109
	if ((btmp=BIO_new(BIO_f_md())) == NULL)
sl@0
   110
		{
sl@0
   111
		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
sl@0
   112
		goto err;
sl@0
   113
		}
sl@0
   114
sl@0
   115
	md=EVP_get_digestbyobj(alg->algorithm);
sl@0
   116
	if (md == NULL)
sl@0
   117
		{
sl@0
   118
		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
sl@0
   119
		goto err;
sl@0
   120
		}
sl@0
   121
sl@0
   122
	BIO_set_md(btmp,md);
sl@0
   123
	if (*pbio == NULL)
sl@0
   124
		*pbio=btmp;
sl@0
   125
	else if (!BIO_push(*pbio,btmp))
sl@0
   126
		{
sl@0
   127
		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
sl@0
   128
		goto err;
sl@0
   129
		}
sl@0
   130
	btmp=NULL;
sl@0
   131
sl@0
   132
	return 1;
sl@0
   133
sl@0
   134
	err:
sl@0
   135
	if (btmp)
sl@0
   136
		BIO_free(btmp);
sl@0
   137
	return 0;
sl@0
   138
sl@0
   139
	}
sl@0
   140
sl@0
   141
EXPORT_C BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
sl@0
   142
	{
sl@0
   143
	int i;
sl@0
   144
	BIO *out=NULL,*btmp=NULL;
sl@0
   145
	X509_ALGOR *xa = NULL;
sl@0
   146
	const EVP_CIPHER *evp_cipher=NULL;
sl@0
   147
	STACK_OF(X509_ALGOR) *md_sk=NULL;
sl@0
   148
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
sl@0
   149
	X509_ALGOR *xalg=NULL;
sl@0
   150
	PKCS7_RECIP_INFO *ri=NULL;
sl@0
   151
	EVP_PKEY *pkey;
sl@0
   152
	ASN1_OCTET_STRING *os=NULL;
sl@0
   153
sl@0
   154
	i=OBJ_obj2nid(p7->type);
sl@0
   155
	p7->state=PKCS7_S_HEADER;
sl@0
   156
sl@0
   157
	switch (i)
sl@0
   158
		{
sl@0
   159
	case NID_pkcs7_signed:
sl@0
   160
		md_sk=p7->d.sign->md_algs;
sl@0
   161
		os = PKCS7_get_octet_string(p7->d.sign->contents);
sl@0
   162
		break;
sl@0
   163
	case NID_pkcs7_signedAndEnveloped:
sl@0
   164
		rsk=p7->d.signed_and_enveloped->recipientinfo;
sl@0
   165
		md_sk=p7->d.signed_and_enveloped->md_algs;
sl@0
   166
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
sl@0
   167
		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
sl@0
   168
		if (evp_cipher == NULL)
sl@0
   169
			{
sl@0
   170
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
sl@0
   171
						PKCS7_R_CIPHER_NOT_INITIALIZED);
sl@0
   172
			goto err;
sl@0
   173
			}
sl@0
   174
		break;
sl@0
   175
	case NID_pkcs7_enveloped:
sl@0
   176
		rsk=p7->d.enveloped->recipientinfo;
sl@0
   177
		xalg=p7->d.enveloped->enc_data->algorithm;
sl@0
   178
		evp_cipher=p7->d.enveloped->enc_data->cipher;
sl@0
   179
		if (evp_cipher == NULL)
sl@0
   180
			{
sl@0
   181
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
sl@0
   182
						PKCS7_R_CIPHER_NOT_INITIALIZED);
sl@0
   183
			goto err;
sl@0
   184
			}
sl@0
   185
		break;
sl@0
   186
	case NID_pkcs7_digest:
sl@0
   187
		xa = p7->d.digest->md;
sl@0
   188
		os = PKCS7_get_octet_string(p7->d.digest->contents);
sl@0
   189
		break;
sl@0
   190
	default:
sl@0
   191
		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
sl@0
   192
	        goto err;
sl@0
   193
		}
sl@0
   194
sl@0
   195
	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
sl@0
   196
		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
sl@0
   197
			goto err;
sl@0
   198
sl@0
   199
	if (xa && !PKCS7_bio_add_digest(&out, xa))
sl@0
   200
			goto err;
sl@0
   201
sl@0
   202
	if (evp_cipher != NULL)
sl@0
   203
		{
sl@0
   204
		unsigned char key[EVP_MAX_KEY_LENGTH];
sl@0
   205
		unsigned char iv[EVP_MAX_IV_LENGTH];
sl@0
   206
		int keylen,ivlen;
sl@0
   207
		int jj,max;
sl@0
   208
		unsigned char *tmp;
sl@0
   209
		EVP_CIPHER_CTX *ctx;
sl@0
   210
sl@0
   211
		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
sl@0
   212
			{
sl@0
   213
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
sl@0
   214
			goto err;
sl@0
   215
			}
sl@0
   216
		BIO_get_cipher_ctx(btmp, &ctx);
sl@0
   217
		keylen=EVP_CIPHER_key_length(evp_cipher);
sl@0
   218
		ivlen=EVP_CIPHER_iv_length(evp_cipher);
sl@0
   219
		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
sl@0
   220
		if (ivlen > 0)
sl@0
   221
			if (RAND_pseudo_bytes(iv,ivlen) <= 0)
sl@0
   222
				goto err;
sl@0
   223
		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
sl@0
   224
			goto err;
sl@0
   225
		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
sl@0
   226
			goto err;
sl@0
   227
		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
sl@0
   228
			goto err;
sl@0
   229
sl@0
   230
		if (ivlen > 0) {
sl@0
   231
			if (xalg->parameter == NULL) {
sl@0
   232
				xalg->parameter = ASN1_TYPE_new();
sl@0
   233
				if (xalg->parameter == NULL)
sl@0
   234
					goto err;
sl@0
   235
			}
sl@0
   236
			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
sl@0
   237
								       goto err;
sl@0
   238
		}
sl@0
   239
sl@0
   240
		/* Lets do the pub key stuff :-) */
sl@0
   241
		max=0;
sl@0
   242
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
sl@0
   243
			{
sl@0
   244
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
sl@0
   245
			if (ri->cert == NULL)
sl@0
   246
				{
sl@0
   247
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
sl@0
   248
				goto err;
sl@0
   249
				}
sl@0
   250
			if ((pkey=X509_get_pubkey(ri->cert)) == NULL)
sl@0
   251
				goto err;
sl@0
   252
			jj=EVP_PKEY_size(pkey);
sl@0
   253
			EVP_PKEY_free(pkey);
sl@0
   254
			if (max < jj) max=jj;
sl@0
   255
			}
sl@0
   256
		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
sl@0
   257
			{
sl@0
   258
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
sl@0
   259
			goto err;
sl@0
   260
			}
sl@0
   261
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
sl@0
   262
			{
sl@0
   263
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
sl@0
   264
			if ((pkey=X509_get_pubkey(ri->cert)) == NULL)
sl@0
   265
				goto err;
sl@0
   266
			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
sl@0
   267
			EVP_PKEY_free(pkey);
sl@0
   268
			if (jj <= 0)
sl@0
   269
				{
sl@0
   270
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
sl@0
   271
				OPENSSL_free(tmp);
sl@0
   272
				goto err;
sl@0
   273
				}
sl@0
   274
			if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
sl@0
   275
				{
sl@0
   276
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,
sl@0
   277
					ERR_R_MALLOC_FAILURE);
sl@0
   278
				OPENSSL_free(tmp);
sl@0
   279
				goto err;
sl@0
   280
				}
sl@0
   281
			}
sl@0
   282
		OPENSSL_free(tmp);
sl@0
   283
		OPENSSL_cleanse(key, keylen);
sl@0
   284
sl@0
   285
		if (out == NULL)
sl@0
   286
			out=btmp;
sl@0
   287
		else
sl@0
   288
			BIO_push(out,btmp);
sl@0
   289
		btmp=NULL;
sl@0
   290
		}
sl@0
   291
sl@0
   292
	if (bio == NULL)
sl@0
   293
		{
sl@0
   294
		if (PKCS7_is_detached(p7))
sl@0
   295
			bio=BIO_new(BIO_s_null());
sl@0
   296
		else if (os && os->length > 0)
sl@0
   297
			bio = BIO_new_mem_buf(os->data, os->length);
sl@0
   298
		if(bio == NULL)
sl@0
   299
			{
sl@0
   300
			bio=BIO_new(BIO_s_mem());
sl@0
   301
			if (bio == NULL)
sl@0
   302
				goto err;
sl@0
   303
			BIO_set_mem_eof_return(bio,0);
sl@0
   304
			}
sl@0
   305
		}
sl@0
   306
	BIO_push(out,bio);
sl@0
   307
	bio=NULL;
sl@0
   308
	if (0)
sl@0
   309
		{
sl@0
   310
err:
sl@0
   311
		if (out != NULL)
sl@0
   312
			BIO_free_all(out);
sl@0
   313
		if (btmp != NULL)
sl@0
   314
			BIO_free_all(btmp);
sl@0
   315
		out=NULL;
sl@0
   316
		}
sl@0
   317
	return(out);
sl@0
   318
	}
sl@0
   319
sl@0
   320
static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
sl@0
   321
	{
sl@0
   322
	int ret;
sl@0
   323
	ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
sl@0
   324
				pcert->cert_info->issuer);
sl@0
   325
	if (ret)
sl@0
   326
		return ret;
sl@0
   327
	return M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
sl@0
   328
					ri->issuer_and_serial->serial);
sl@0
   329
	}
sl@0
   330
sl@0
   331
/* int */
sl@0
   332
EXPORT_C BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
sl@0
   333
	{
sl@0
   334
	int i,j;
sl@0
   335
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
sl@0
   336
	unsigned char *tmp=NULL;
sl@0
   337
	X509_ALGOR *xa;
sl@0
   338
	ASN1_OCTET_STRING *data_body=NULL;
sl@0
   339
	const EVP_MD *evp_md;
sl@0
   340
	const EVP_CIPHER *evp_cipher=NULL;
sl@0
   341
	EVP_CIPHER_CTX *evp_ctx=NULL;
sl@0
   342
	X509_ALGOR *enc_alg=NULL;
sl@0
   343
	STACK_OF(X509_ALGOR) *md_sk=NULL;
sl@0
   344
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
sl@0
   345
	X509_ALGOR *xalg=NULL;
sl@0
   346
	PKCS7_RECIP_INFO *ri=NULL;
sl@0
   347
sl@0
   348
	i=OBJ_obj2nid(p7->type);
sl@0
   349
	p7->state=PKCS7_S_HEADER;
sl@0
   350
sl@0
   351
	switch (i)
sl@0
   352
		{
sl@0
   353
	case NID_pkcs7_signed:
sl@0
   354
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
sl@0
   355
		md_sk=p7->d.sign->md_algs;
sl@0
   356
		break;
sl@0
   357
	case NID_pkcs7_signedAndEnveloped:
sl@0
   358
		rsk=p7->d.signed_and_enveloped->recipientinfo;
sl@0
   359
		md_sk=p7->d.signed_and_enveloped->md_algs;
sl@0
   360
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
sl@0
   361
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
sl@0
   362
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
sl@0
   363
		if (evp_cipher == NULL)
sl@0
   364
			{
sl@0
   365
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
sl@0
   366
			goto err;
sl@0
   367
			}
sl@0
   368
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
sl@0
   369
		break;
sl@0
   370
	case NID_pkcs7_enveloped:
sl@0
   371
		rsk=p7->d.enveloped->recipientinfo;
sl@0
   372
		enc_alg=p7->d.enveloped->enc_data->algorithm;
sl@0
   373
		data_body=p7->d.enveloped->enc_data->enc_data;
sl@0
   374
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
sl@0
   375
		if (evp_cipher == NULL)
sl@0
   376
			{
sl@0
   377
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
sl@0
   378
			goto err;
sl@0
   379
			}
sl@0
   380
		xalg=p7->d.enveloped->enc_data->algorithm;
sl@0
   381
		break;
sl@0
   382
	default:
sl@0
   383
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
sl@0
   384
	        goto err;
sl@0
   385
		}
sl@0
   386
sl@0
   387
	/* We will be checking the signature */
sl@0
   388
	if (md_sk != NULL)
sl@0
   389
		{
sl@0
   390
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
sl@0
   391
			{
sl@0
   392
			xa=sk_X509_ALGOR_value(md_sk,i);
sl@0
   393
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
sl@0
   394
				{
sl@0
   395
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
sl@0
   396
				goto err;
sl@0
   397
				}
sl@0
   398
sl@0
   399
			j=OBJ_obj2nid(xa->algorithm);
sl@0
   400
			evp_md=EVP_get_digestbynid(j);
sl@0
   401
			if (evp_md == NULL)
sl@0
   402
				{
sl@0
   403
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
sl@0
   404
				goto err;
sl@0
   405
				}
sl@0
   406
sl@0
   407
			BIO_set_md(btmp,evp_md);
sl@0
   408
			if (out == NULL)
sl@0
   409
				out=btmp;
sl@0
   410
			else
sl@0
   411
				BIO_push(out,btmp);
sl@0
   412
			btmp=NULL;
sl@0
   413
			}
sl@0
   414
		}
sl@0
   415
sl@0
   416
	if (evp_cipher != NULL)
sl@0
   417
		{
sl@0
   418
#if 0
sl@0
   419
		unsigned char key[EVP_MAX_KEY_LENGTH];
sl@0
   420
		unsigned char iv[EVP_MAX_IV_LENGTH];
sl@0
   421
		unsigned char *p;
sl@0
   422
		int keylen,ivlen;
sl@0
   423
		int max;
sl@0
   424
		X509_OBJECT ret;
sl@0
   425
#endif
sl@0
   426
		int jj;
sl@0
   427
sl@0
   428
		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
sl@0
   429
			{
sl@0
   430
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
sl@0
   431
			goto err;
sl@0
   432
			}
sl@0
   433
sl@0
   434
		/* It was encrypted, we need to decrypt the secret key
sl@0
   435
		 * with the private key */
sl@0
   436
sl@0
   437
		/* Find the recipientInfo which matches the passed certificate
sl@0
   438
		 * (if any)
sl@0
   439
		 */
sl@0
   440
sl@0
   441
		if (pcert) {
sl@0
   442
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
sl@0
   443
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
sl@0
   444
				if (!pkcs7_cmp_ri(ri, pcert))
sl@0
   445
					break;
sl@0
   446
				ri=NULL;
sl@0
   447
			}
sl@0
   448
			if (ri == NULL) {
sl@0
   449
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
sl@0
   450
				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
sl@0
   451
				goto err;
sl@0
   452
			}
sl@0
   453
		}
sl@0
   454
sl@0
   455
		jj=EVP_PKEY_size(pkey);
sl@0
   456
		tmp=(unsigned char *)OPENSSL_malloc(jj+10);
sl@0
   457
		if (tmp == NULL)
sl@0
   458
			{
sl@0
   459
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
sl@0
   460
			goto err;
sl@0
   461
			}
sl@0
   462
sl@0
   463
		/* If we haven't got a certificate try each ri in turn */
sl@0
   464
sl@0
   465
		if (pcert == NULL)
sl@0
   466
			{
sl@0
   467
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
sl@0
   468
				{
sl@0
   469
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
sl@0
   470
				jj=EVP_PKEY_decrypt(tmp,
sl@0
   471
					M_ASN1_STRING_data(ri->enc_key),
sl@0
   472
					M_ASN1_STRING_length(ri->enc_key),
sl@0
   473
						pkey);
sl@0
   474
				if (jj > 0)
sl@0
   475
					break;
sl@0
   476
				ERR_clear_error();
sl@0
   477
				ri = NULL;
sl@0
   478
				}
sl@0
   479
			if (ri == NULL)
sl@0
   480
				{
sl@0
   481
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
sl@0
   482
				      PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
sl@0
   483
				goto err;
sl@0
   484
				}
sl@0
   485
			}
sl@0
   486
		else
sl@0
   487
			{
sl@0
   488
			jj=EVP_PKEY_decrypt(tmp,
sl@0
   489
				M_ASN1_STRING_data(ri->enc_key),
sl@0
   490
				M_ASN1_STRING_length(ri->enc_key), pkey);
sl@0
   491
			if (jj <= 0)
sl@0
   492
				{
sl@0
   493
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
sl@0
   494
								ERR_R_EVP_LIB);
sl@0
   495
				goto err;
sl@0
   496
				}
sl@0
   497
			}
sl@0
   498
sl@0
   499
		evp_ctx=NULL;
sl@0
   500
		BIO_get_cipher_ctx(etmp,&evp_ctx);
sl@0
   501
		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
sl@0
   502
			goto err;
sl@0
   503
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
sl@0
   504
			goto err;
sl@0
   505
sl@0
   506
		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
sl@0
   507
			/* Some S/MIME clients don't use the same key
sl@0
   508
			 * and effective key length. The key length is
sl@0
   509
			 * determined by the size of the decrypted RSA key.
sl@0
   510
			 */
sl@0
   511
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
sl@0
   512
				{
sl@0
   513
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
sl@0
   514
					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
sl@0
   515
				goto err;
sl@0
   516
				}
sl@0
   517
		} 
sl@0
   518
		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
sl@0
   519
			goto err;
sl@0
   520
sl@0
   521
		OPENSSL_cleanse(tmp,jj);
sl@0
   522
sl@0
   523
		if (out == NULL)
sl@0
   524
			out=etmp;
sl@0
   525
		else
sl@0
   526
			BIO_push(out,etmp);
sl@0
   527
		etmp=NULL;
sl@0
   528
		}
sl@0
   529
sl@0
   530
#if 1
sl@0
   531
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
sl@0
   532
		{
sl@0
   533
		bio=in_bio;
sl@0
   534
		}
sl@0
   535
	else 
sl@0
   536
		{
sl@0
   537
#if 0
sl@0
   538
		bio=BIO_new(BIO_s_mem());
sl@0
   539
		/* We need to set this so that when we have read all
sl@0
   540
		 * the data, the encrypt BIO, if present, will read
sl@0
   541
		 * EOF and encode the last few bytes */
sl@0
   542
		BIO_set_mem_eof_return(bio,0);
sl@0
   543
sl@0
   544
		if (data_body->length > 0)
sl@0
   545
			BIO_write(bio,(char *)data_body->data,data_body->length);
sl@0
   546
#else
sl@0
   547
		if (data_body->length > 0)
sl@0
   548
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
sl@0
   549
		else {
sl@0
   550
			bio=BIO_new(BIO_s_mem());
sl@0
   551
			BIO_set_mem_eof_return(bio,0);
sl@0
   552
		}
sl@0
   553
		if (bio == NULL)
sl@0
   554
			goto err;
sl@0
   555
#endif
sl@0
   556
		}
sl@0
   557
	BIO_push(out,bio);
sl@0
   558
	bio=NULL;
sl@0
   559
#endif
sl@0
   560
	if (0)
sl@0
   561
		{
sl@0
   562
err:
sl@0
   563
		if (out != NULL) BIO_free_all(out);
sl@0
   564
		if (btmp != NULL) BIO_free_all(btmp);
sl@0
   565
		if (etmp != NULL) BIO_free_all(etmp);
sl@0
   566
		if (bio != NULL) BIO_free_all(bio);
sl@0
   567
		out=NULL;
sl@0
   568
		}
sl@0
   569
	if (tmp != NULL)
sl@0
   570
		OPENSSL_free(tmp);
sl@0
   571
	return(out);
sl@0
   572
	}
sl@0
   573
sl@0
   574
static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
sl@0
   575
	{
sl@0
   576
	for (;;)
sl@0
   577
		{
sl@0
   578
		bio=BIO_find_type(bio,BIO_TYPE_MD);
sl@0
   579
		if (bio == NULL)
sl@0
   580
			{
sl@0
   581
			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
sl@0
   582
			return NULL;	
sl@0
   583
			}
sl@0
   584
		BIO_get_md_ctx(bio,pmd);
sl@0
   585
		if (*pmd == NULL)
sl@0
   586
			{
sl@0
   587
			PKCS7err(PKCS7_F_PKCS7_FIND_DIGEST,ERR_R_INTERNAL_ERROR);
sl@0
   588
			return NULL;
sl@0
   589
			}	
sl@0
   590
		if (EVP_MD_CTX_type(*pmd) == nid)
sl@0
   591
			return bio;
sl@0
   592
		bio=BIO_next(bio);
sl@0
   593
		}
sl@0
   594
	return NULL;
sl@0
   595
	}
sl@0
   596
sl@0
   597
EXPORT_C int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
sl@0
   598
	{
sl@0
   599
	int ret=0;
sl@0
   600
	int i,j;
sl@0
   601
	BIO *btmp;
sl@0
   602
	BUF_MEM *buf_mem=NULL;
sl@0
   603
	BUF_MEM *buf=NULL;
sl@0
   604
	PKCS7_SIGNER_INFO *si;
sl@0
   605
	EVP_MD_CTX *mdc,ctx_tmp;
sl@0
   606
	STACK_OF(X509_ATTRIBUTE) *sk;
sl@0
   607
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
sl@0
   608
	ASN1_OCTET_STRING *os=NULL;
sl@0
   609
sl@0
   610
	EVP_MD_CTX_init(&ctx_tmp);
sl@0
   611
	i=OBJ_obj2nid(p7->type);
sl@0
   612
	p7->state=PKCS7_S_HEADER;
sl@0
   613
sl@0
   614
	switch (i)
sl@0
   615
		{
sl@0
   616
	case NID_pkcs7_signedAndEnveloped:
sl@0
   617
		/* XXXXXXXXXXXXXXXX */
sl@0
   618
		si_sk=p7->d.signed_and_enveloped->signer_info;
sl@0
   619
		if (!(os=M_ASN1_OCTET_STRING_new()))
sl@0
   620
			{
sl@0
   621
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
sl@0
   622
			goto err;
sl@0
   623
			}
sl@0
   624
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
sl@0
   625
		break;
sl@0
   626
	case NID_pkcs7_enveloped:
sl@0
   627
		/* XXXXXXXXXXXXXXXX */
sl@0
   628
		if (!(os=M_ASN1_OCTET_STRING_new()))
sl@0
   629
			{
sl@0
   630
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
sl@0
   631
			goto err;
sl@0
   632
			}
sl@0
   633
		p7->d.enveloped->enc_data->enc_data=os;
sl@0
   634
		break;
sl@0
   635
	case NID_pkcs7_signed:
sl@0
   636
		si_sk=p7->d.sign->signer_info;
sl@0
   637
		os=PKCS7_get_octet_string(p7->d.sign->contents);
sl@0
   638
		/* If detached data then the content is excluded */
sl@0
   639
		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
sl@0
   640
			M_ASN1_OCTET_STRING_free(os);
sl@0
   641
			p7->d.sign->contents->d.data = NULL;
sl@0
   642
		}
sl@0
   643
		break;
sl@0
   644
sl@0
   645
	case NID_pkcs7_digest:
sl@0
   646
		os=PKCS7_get_octet_string(p7->d.digest->contents);
sl@0
   647
		/* If detached data then the content is excluded */
sl@0
   648
		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
sl@0
   649
			{
sl@0
   650
			M_ASN1_OCTET_STRING_free(os);
sl@0
   651
			p7->d.digest->contents->d.data = NULL;
sl@0
   652
			}
sl@0
   653
		break;
sl@0
   654
sl@0
   655
		}
sl@0
   656
sl@0
   657
	if (si_sk != NULL)
sl@0
   658
		{
sl@0
   659
		if ((buf=BUF_MEM_new()) == NULL)
sl@0
   660
			{
sl@0
   661
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
sl@0
   662
			goto err;
sl@0
   663
			}
sl@0
   664
		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
sl@0
   665
			{
sl@0
   666
			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
sl@0
   667
			if (si->pkey == NULL) continue;
sl@0
   668
sl@0
   669
			j=OBJ_obj2nid(si->digest_alg->algorithm);
sl@0
   670
sl@0
   671
			btmp=bio;
sl@0
   672
sl@0
   673
			btmp = PKCS7_find_digest(&mdc, btmp, j);
sl@0
   674
sl@0
   675
			if (btmp == NULL)
sl@0
   676
				goto err;
sl@0
   677
sl@0
   678
			/* We now have the EVP_MD_CTX, lets do the
sl@0
   679
			 * signing. */
sl@0
   680
			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
sl@0
   681
			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
sl@0
   682
				{
sl@0
   683
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
sl@0
   684
				goto err;
sl@0
   685
				}
sl@0
   686
sl@0
   687
			sk=si->auth_attr;
sl@0
   688
sl@0
   689
			/* If there are attributes, we add the digest
sl@0
   690
			 * attribute and only sign the attributes */
sl@0
   691
			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
sl@0
   692
				{
sl@0
   693
				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
sl@0
   694
				unsigned int md_len, alen;
sl@0
   695
				ASN1_OCTET_STRING *digest;
sl@0
   696
				ASN1_UTCTIME *sign_time;
sl@0
   697
				const EVP_MD *md_tmp;
sl@0
   698
sl@0
   699
				/* Add signing time if not already present */
sl@0
   700
				if (!PKCS7_get_signed_attribute(si,
sl@0
   701
							NID_pkcs9_signingTime))
sl@0
   702
					{
sl@0
   703
					if (!(sign_time=X509_gmtime_adj(NULL,0)))
sl@0
   704
						{
sl@0
   705
						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
sl@0
   706
							ERR_R_MALLOC_FAILURE);
sl@0
   707
						goto err;
sl@0
   708
						}
sl@0
   709
					if (!PKCS7_add_signed_attribute(si,
sl@0
   710
						NID_pkcs9_signingTime,
sl@0
   711
						V_ASN1_UTCTIME,sign_time))
sl@0
   712
						{
sl@0
   713
						M_ASN1_UTCTIME_free(sign_time);
sl@0
   714
						goto err;
sl@0
   715
						}
sl@0
   716
					}
sl@0
   717
sl@0
   718
				/* Add digest */
sl@0
   719
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
sl@0
   720
				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
sl@0
   721
				if (!(digest=M_ASN1_OCTET_STRING_new()))
sl@0
   722
					{
sl@0
   723
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
sl@0
   724
						ERR_R_MALLOC_FAILURE);
sl@0
   725
					goto err;
sl@0
   726
					}
sl@0
   727
				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
sl@0
   728
								md_len))
sl@0
   729
					{
sl@0
   730
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
sl@0
   731
						ERR_R_MALLOC_FAILURE);
sl@0
   732
					M_ASN1_OCTET_STRING_free(digest);
sl@0
   733
					goto err;
sl@0
   734
					}
sl@0
   735
				if (!PKCS7_add_signed_attribute(si,
sl@0
   736
					NID_pkcs9_messageDigest,
sl@0
   737
					V_ASN1_OCTET_STRING,digest))
sl@0
   738
					{
sl@0
   739
					M_ASN1_OCTET_STRING_free(digest);
sl@0
   740
					goto err;
sl@0
   741
					}
sl@0
   742
sl@0
   743
				/* Now sign the attributes */
sl@0
   744
				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
sl@0
   745
				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
sl@0
   746
							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
sl@0
   747
				if(!abuf) goto err;
sl@0
   748
				EVP_SignUpdate(&ctx_tmp,abuf,alen);
sl@0
   749
				OPENSSL_free(abuf);
sl@0
   750
				}
sl@0
   751
sl@0
   752
#ifndef OPENSSL_NO_DSA
sl@0
   753
			if (si->pkey->type == EVP_PKEY_DSA)
sl@0
   754
				ctx_tmp.digest=EVP_dss1();
sl@0
   755
#endif
sl@0
   756
#ifndef OPENSSL_NO_ECDSA
sl@0
   757
 			if (si->pkey->type == EVP_PKEY_EC)
sl@0
   758
 				ctx_tmp.digest=EVP_ecdsa();
sl@0
   759
#endif
sl@0
   760
sl@0
   761
			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
sl@0
   762
				(unsigned int *)&buf->length,si->pkey))
sl@0
   763
				{
sl@0
   764
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
sl@0
   765
				goto err;
sl@0
   766
				}
sl@0
   767
			if (!ASN1_STRING_set(si->enc_digest,
sl@0
   768
				(unsigned char *)buf->data,buf->length))
sl@0
   769
				{
sl@0
   770
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
sl@0
   771
				goto err;
sl@0
   772
				}
sl@0
   773
			}
sl@0
   774
		}
sl@0
   775
	else if (i == NID_pkcs7_digest)
sl@0
   776
		{
sl@0
   777
		unsigned char md_data[EVP_MAX_MD_SIZE];
sl@0
   778
		unsigned int md_len;
sl@0
   779
		if (!PKCS7_find_digest(&mdc, bio,
sl@0
   780
				OBJ_obj2nid(p7->d.digest->md->algorithm)))
sl@0
   781
			goto err;
sl@0
   782
		EVP_DigestFinal_ex(mdc,md_data,&md_len);
sl@0
   783
		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
sl@0
   784
		}
sl@0
   785
sl@0
   786
	if (!PKCS7_is_detached(p7))
sl@0
   787
		{
sl@0
   788
		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
sl@0
   789
		if (btmp == NULL)
sl@0
   790
			{
sl@0
   791
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
sl@0
   792
			goto err;
sl@0
   793
			}
sl@0
   794
		BIO_get_mem_ptr(btmp,&buf_mem);
sl@0
   795
		/* Mark the BIO read only then we can use its copy of the data
sl@0
   796
		 * instead of making an extra copy.
sl@0
   797
		 */
sl@0
   798
		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
sl@0
   799
		BIO_set_mem_eof_return(btmp, 0);
sl@0
   800
		os->data = (unsigned char *)buf_mem->data;
sl@0
   801
		os->length = buf_mem->length;
sl@0
   802
#if 0
sl@0
   803
		M_ASN1_OCTET_STRING_set(os,
sl@0
   804
			(unsigned char *)buf_mem->data,buf_mem->length);
sl@0
   805
#endif
sl@0
   806
		}
sl@0
   807
	ret=1;
sl@0
   808
err:
sl@0
   809
	EVP_MD_CTX_cleanup(&ctx_tmp);
sl@0
   810
	if (buf != NULL) BUF_MEM_free(buf);
sl@0
   811
	return(ret);
sl@0
   812
	}
sl@0
   813
sl@0
   814
EXPORT_C int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
sl@0
   815
	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
sl@0
   816
	{
sl@0
   817
	PKCS7_ISSUER_AND_SERIAL *ias;
sl@0
   818
	int ret=0,i;
sl@0
   819
	STACK_OF(X509) *cert;
sl@0
   820
	X509 *x509;
sl@0
   821
sl@0
   822
	if (PKCS7_type_is_signed(p7))
sl@0
   823
		{
sl@0
   824
		cert=p7->d.sign->cert;
sl@0
   825
		}
sl@0
   826
	else if (PKCS7_type_is_signedAndEnveloped(p7))
sl@0
   827
		{
sl@0
   828
		cert=p7->d.signed_and_enveloped->cert;
sl@0
   829
		}
sl@0
   830
	else
sl@0
   831
		{
sl@0
   832
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
sl@0
   833
		goto err;
sl@0
   834
		}
sl@0
   835
	/* XXXXXXXXXXXXXXXXXXXXXXX */
sl@0
   836
	ias=si->issuer_and_serial;
sl@0
   837
sl@0
   838
	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
sl@0
   839
sl@0
   840
	/* were we able to find the cert in passed to us */
sl@0
   841
	if (x509 == NULL)
sl@0
   842
		{
sl@0
   843
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
sl@0
   844
		goto err;
sl@0
   845
		}
sl@0
   846
sl@0
   847
	/* Lets verify */
sl@0
   848
	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
sl@0
   849
		{
sl@0
   850
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
sl@0
   851
		goto err;
sl@0
   852
		}
sl@0
   853
	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
sl@0
   854
	i=X509_verify_cert(ctx);
sl@0
   855
	if (i <= 0) 
sl@0
   856
		{
sl@0
   857
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
sl@0
   858
		X509_STORE_CTX_cleanup(ctx);
sl@0
   859
		goto err;
sl@0
   860
		}
sl@0
   861
	X509_STORE_CTX_cleanup(ctx);
sl@0
   862
sl@0
   863
	return PKCS7_signatureVerify(bio, p7, si, x509);
sl@0
   864
	err:
sl@0
   865
	return ret;
sl@0
   866
	}
sl@0
   867
sl@0
   868
EXPORT_C int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
sl@0
   869
								X509 *x509)
sl@0
   870
	{
sl@0
   871
	ASN1_OCTET_STRING *os;
sl@0
   872
	EVP_MD_CTX mdc_tmp,*mdc;
sl@0
   873
	int ret=0,i;
sl@0
   874
	int md_type;
sl@0
   875
	STACK_OF(X509_ATTRIBUTE) *sk;
sl@0
   876
	BIO *btmp;
sl@0
   877
	EVP_PKEY *pkey;
sl@0
   878
sl@0
   879
	EVP_MD_CTX_init(&mdc_tmp);
sl@0
   880
sl@0
   881
	if (!PKCS7_type_is_signed(p7) && 
sl@0
   882
				!PKCS7_type_is_signedAndEnveloped(p7)) {
sl@0
   883
		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
sl@0
   884
						PKCS7_R_WRONG_PKCS7_TYPE);
sl@0
   885
		goto err;
sl@0
   886
	}
sl@0
   887
sl@0
   888
	md_type=OBJ_obj2nid(si->digest_alg->algorithm);
sl@0
   889
sl@0
   890
	btmp=bio;
sl@0
   891
	for (;;)
sl@0
   892
		{
sl@0
   893
		if ((btmp == NULL) ||
sl@0
   894
			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
sl@0
   895
			{
sl@0
   896
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
sl@0
   897
					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
sl@0
   898
			goto err;
sl@0
   899
			}
sl@0
   900
		BIO_get_md_ctx(btmp,&mdc);
sl@0
   901
		if (mdc == NULL)
sl@0
   902
			{
sl@0
   903
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
sl@0
   904
							ERR_R_INTERNAL_ERROR);
sl@0
   905
			goto err;
sl@0
   906
			}
sl@0
   907
		if (EVP_MD_CTX_type(mdc) == md_type)
sl@0
   908
			break;
sl@0
   909
		/* Workaround for some broken clients that put the signature
sl@0
   910
		 * OID instead of the digest OID in digest_alg->algorithm
sl@0
   911
		 */
sl@0
   912
		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
sl@0
   913
			break;
sl@0
   914
		btmp=BIO_next(btmp);
sl@0
   915
		}
sl@0
   916
sl@0
   917
	/* mdc is the digest ctx that we want, unless there are attributes,
sl@0
   918
	 * in which case the digest is the signed attributes */
sl@0
   919
	EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
sl@0
   920
sl@0
   921
	sk=si->auth_attr;
sl@0
   922
	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
sl@0
   923
		{
sl@0
   924
		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
sl@0
   925
                unsigned int md_len, alen;
sl@0
   926
		ASN1_OCTET_STRING *message_digest;
sl@0
   927
sl@0
   928
		EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
sl@0
   929
		message_digest=PKCS7_digest_from_attributes(sk);
sl@0
   930
		if (!message_digest)
sl@0
   931
			{
sl@0
   932
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
sl@0
   933
					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
sl@0
   934
			goto err;
sl@0
   935
			}
sl@0
   936
		if ((message_digest->length != (int)md_len) ||
sl@0
   937
			(memcmp(message_digest->data,md_dat,md_len)))
sl@0
   938
			{
sl@0
   939
#if 0
sl@0
   940
{
sl@0
   941
int ii;
sl@0
   942
for (ii=0; ii<message_digest->length; ii++)
sl@0
   943
	printf("%02X",message_digest->data[ii]); printf(" sent\n");
sl@0
   944
for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
sl@0
   945
}
sl@0
   946
#endif
sl@0
   947
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
sl@0
   948
							PKCS7_R_DIGEST_FAILURE);
sl@0
   949
			ret= -1;
sl@0
   950
			goto err;
sl@0
   951
			}
sl@0
   952
sl@0
   953
		EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL);
sl@0
   954
sl@0
   955
		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
sl@0
   956
						ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
sl@0
   957
		EVP_VerifyUpdate(&mdc_tmp, abuf, alen);
sl@0
   958
sl@0
   959
		OPENSSL_free(abuf);
sl@0
   960
		}
sl@0
   961
sl@0
   962
	os=si->enc_digest;
sl@0
   963
	pkey = X509_get_pubkey(x509);
sl@0
   964
	if (!pkey)
sl@0
   965
		{
sl@0
   966
		ret = -1;
sl@0
   967
		goto err;
sl@0
   968
		}
sl@0
   969
#ifndef OPENSSL_NO_DSA
sl@0
   970
	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
sl@0
   971
#endif
sl@0
   972
#ifndef OPENSSL_NO_ECDSA
sl@0
   973
	if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
sl@0
   974
#endif
sl@0
   975
sl@0
   976
	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
sl@0
   977
	EVP_PKEY_free(pkey);
sl@0
   978
	if (i <= 0)
sl@0
   979
		{
sl@0
   980
		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
sl@0
   981
						PKCS7_R_SIGNATURE_FAILURE);
sl@0
   982
		ret= -1;
sl@0
   983
		goto err;
sl@0
   984
		}
sl@0
   985
	else
sl@0
   986
		ret=1;
sl@0
   987
err:
sl@0
   988
	EVP_MD_CTX_cleanup(&mdc_tmp);
sl@0
   989
	return(ret);
sl@0
   990
	}
sl@0
   991
sl@0
   992
EXPORT_C PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
sl@0
   993
	{
sl@0
   994
	STACK_OF(PKCS7_RECIP_INFO) *rsk;
sl@0
   995
	PKCS7_RECIP_INFO *ri;
sl@0
   996
	int i;
sl@0
   997
sl@0
   998
	i=OBJ_obj2nid(p7->type);
sl@0
   999
	if (i != NID_pkcs7_signedAndEnveloped)
sl@0
  1000
		return NULL;
sl@0
  1001
	if (p7->d.signed_and_enveloped == NULL)
sl@0
  1002
		return NULL;
sl@0
  1003
	rsk=p7->d.signed_and_enveloped->recipientinfo;
sl@0
  1004
	if (rsk == NULL)
sl@0
  1005
		return NULL;
sl@0
  1006
	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
sl@0
  1007
	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
sl@0
  1008
	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
sl@0
  1009
	return(ri->issuer_and_serial);
sl@0
  1010
	}
sl@0
  1011
sl@0
  1012
EXPORT_C ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
sl@0
  1013
	{
sl@0
  1014
	return(get_attribute(si->auth_attr,nid));
sl@0
  1015
	}
sl@0
  1016
sl@0
  1017
EXPORT_C ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
sl@0
  1018
	{
sl@0
  1019
	return(get_attribute(si->unauth_attr,nid));
sl@0
  1020
	}
sl@0
  1021
sl@0
  1022
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
sl@0
  1023
	{
sl@0
  1024
	int i;
sl@0
  1025
	X509_ATTRIBUTE *xa;
sl@0
  1026
	ASN1_OBJECT *o;
sl@0
  1027
sl@0
  1028
	o=OBJ_nid2obj(nid);
sl@0
  1029
	if (!o || !sk) return(NULL);
sl@0
  1030
	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
sl@0
  1031
		{
sl@0
  1032
		xa=sk_X509_ATTRIBUTE_value(sk,i);
sl@0
  1033
		if (OBJ_cmp(xa->object,o) == 0)
sl@0
  1034
			{
sl@0
  1035
			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
sl@0
  1036
				return(sk_ASN1_TYPE_value(xa->value.set,0));
sl@0
  1037
			else
sl@0
  1038
				return(NULL);
sl@0
  1039
			}
sl@0
  1040
		}
sl@0
  1041
	return(NULL);
sl@0
  1042
	}
sl@0
  1043
sl@0
  1044
EXPORT_C ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
sl@0
  1045
{
sl@0
  1046
	ASN1_TYPE *astype;
sl@0
  1047
	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
sl@0
  1048
	return astype->value.octet_string;
sl@0
  1049
}
sl@0
  1050
sl@0
  1051
EXPORT_C int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
sl@0
  1052
				STACK_OF(X509_ATTRIBUTE) *sk)
sl@0
  1053
	{
sl@0
  1054
	int i;
sl@0
  1055
sl@0
  1056
	if (p7si->auth_attr != NULL)
sl@0
  1057
		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
sl@0
  1058
	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
sl@0
  1059
	if (p7si->auth_attr == NULL)
sl@0
  1060
		return 0;
sl@0
  1061
	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
sl@0
  1062
		{
sl@0
  1063
		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
sl@0
  1064
			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
sl@0
  1065
		    == NULL)
sl@0
  1066
			return(0);
sl@0
  1067
		}
sl@0
  1068
	return(1);
sl@0
  1069
	}
sl@0
  1070
sl@0
  1071
EXPORT_C int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
sl@0
  1072
	{
sl@0
  1073
	int i;
sl@0
  1074
sl@0
  1075
	if (p7si->unauth_attr != NULL)
sl@0
  1076
		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
sl@0
  1077
					   X509_ATTRIBUTE_free);
sl@0
  1078
	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
sl@0
  1079
	if (p7si->unauth_attr == NULL)
sl@0
  1080
		return 0;
sl@0
  1081
	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
sl@0
  1082
		{
sl@0
  1083
		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
sl@0
  1084
                        X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
sl@0
  1085
		    == NULL)
sl@0
  1086
			return(0);
sl@0
  1087
		}
sl@0
  1088
	return(1);
sl@0
  1089
	}
sl@0
  1090
sl@0
  1091
EXPORT_C int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
sl@0
  1092
	     void *value)
sl@0
  1093
	{
sl@0
  1094
	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
sl@0
  1095
	}
sl@0
  1096
sl@0
  1097
EXPORT_C int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
sl@0
  1098
	     void *value)
sl@0
  1099
	{
sl@0
  1100
	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
sl@0
  1101
	}
sl@0
  1102
sl@0
  1103
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
sl@0
  1104
			 void *value)
sl@0
  1105
	{
sl@0
  1106
	X509_ATTRIBUTE *attr=NULL;
sl@0
  1107
sl@0
  1108
	if (*sk == NULL)
sl@0
  1109
		{
sl@0
  1110
		if (!(*sk = sk_X509_ATTRIBUTE_new_null()))
sl@0
  1111
			return 0;
sl@0
  1112
new_attrib:
sl@0
  1113
		if (!(attr=X509_ATTRIBUTE_create(nid,atrtype,value)))
sl@0
  1114
			return 0;
sl@0
  1115
		if (!sk_X509_ATTRIBUTE_push(*sk,attr))
sl@0
  1116
			{
sl@0
  1117
			X509_ATTRIBUTE_free(attr);
sl@0
  1118
			return 0;
sl@0
  1119
			}
sl@0
  1120
		}
sl@0
  1121
	else
sl@0
  1122
		{
sl@0
  1123
		int i;
sl@0
  1124
sl@0
  1125
		for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++)
sl@0
  1126
			{
sl@0
  1127
			attr=sk_X509_ATTRIBUTE_value(*sk,i);
sl@0
  1128
			if (OBJ_obj2nid(attr->object) == nid)
sl@0
  1129
				{
sl@0
  1130
				X509_ATTRIBUTE_free(attr);
sl@0
  1131
				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
sl@0
  1132
				if (attr == NULL)
sl@0
  1133
					return 0;
sl@0
  1134
				if (!sk_X509_ATTRIBUTE_set(*sk,i,attr))
sl@0
  1135
					{
sl@0
  1136
					X509_ATTRIBUTE_free(attr);
sl@0
  1137
					return 0;
sl@0
  1138
					}
sl@0
  1139
				goto end;
sl@0
  1140
				}
sl@0
  1141
			}
sl@0
  1142
		goto new_attrib;
sl@0
  1143
		}
sl@0
  1144
end:
sl@0
  1145
	return(1);
sl@0
  1146
	}
sl@0
  1147