pk7_doit.c 25.6 KB
Newer Older
1
/* crypto/pkcs7/pk7_doit.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

#include <stdio.h>
#include "cryptlib.h"
61 62 63
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
64
#include <openssl/x509v3.h>
65

B
Ben Laurie 已提交
66 67 68
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
			 void *value);
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid);
69

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
static int PKCS7_type_is_other(PKCS7* p7)
	{
	int isOther=1;
	
	int nid=OBJ_obj2nid(p7->type);

	switch( nid )
		{
	case NID_pkcs7_data:
	case NID_pkcs7_signed:
	case NID_pkcs7_enveloped:
	case NID_pkcs7_signedAndEnveloped:
	case NID_pkcs7_digest:
	case NID_pkcs7_encrypted:
		isOther=0;
		break;
	default:
		isOther=1;
		}

	return isOther;

	}

94
static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
95
	{
96 97 98 99 100 101
	if ( PKCS7_type_is_data(p7))
		return p7->d.data;
	if ( PKCS7_type_is_other(p7) && p7->d.other
		&& (p7->d.other->type == V_ASN1_OCTET_STRING))
		return p7->d.other->value.octet_string;
	return NULL;
102 103
	}

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
	{
	BIO *btmp;
	const EVP_MD *md;
	if ((btmp=BIO_new(BIO_f_md())) == NULL)
		{
		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
		goto err;
		}

	md=EVP_get_digestbyobj(alg->algorithm);
	if (md == NULL)
		{
		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,PKCS7_R_UNKNOWN_DIGEST_TYPE);
		goto err;
		}

	BIO_set_md(btmp,md);
	if (*pbio == NULL)
		*pbio=btmp;
	else if (!BIO_push(*pbio,btmp))
		{
		PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST,ERR_R_BIO_LIB);
		goto err;
		}
	btmp=NULL;

	return 1;

	err:
	if (btmp)
		BIO_free(btmp);
	return 0;

	}

U
Ulf Möller 已提交
140
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
141
	{
142
	int i;
143
	BIO *out=NULL,*btmp=NULL;
144
	X509_ALGOR *xa = NULL;
B
Ben Laurie 已提交
145
	const EVP_CIPHER *evp_cipher=NULL;
B
Stack.  
Ben Laurie 已提交
146
	STACK_OF(X509_ALGOR) *md_sk=NULL;
B
stack.  
Ben Laurie 已提交
147
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
148 149 150
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	EVP_PKEY *pkey;
151
	ASN1_OCTET_STRING *os=NULL;
152 153 154 155 156 157 158

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
159
		md_sk=p7->d.sign->md_algs;
160
		os = PKCS7_get_octet_string(p7->d.sign->contents);
161 162 163 164
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
165 166
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
167
		if (evp_cipher == NULL)
168
			{
169 170
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
171 172 173
			goto err;
			}
		break;
174 175
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
176 177
		xalg=p7->d.enveloped->enc_data->algorithm;
		evp_cipher=p7->d.enveloped->enc_data->cipher;
178 179
		if (evp_cipher == NULL)
			{
180 181
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
182 183 184
			goto err;
			}
		break;
185 186 187 188
	case NID_pkcs7_digest:
		xa = p7->d.digest->md;
		os = PKCS7_get_octet_string(p7->d.digest->contents);
		break;
189 190 191 192 193
	default:
		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

194 195 196
	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
			goto err;
197

198 199
	if (xa && !PKCS7_bio_add_digest(&out, xa))
			goto err;
200 201 202 203 204 205 206 207

	if (evp_cipher != NULL)
		{
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		int keylen,ivlen;
		int jj,max;
		unsigned char *tmp;
208
		EVP_CIPHER_CTX *ctx;
209

210 211 212 213 214
		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
			goto err;
			}
215
		BIO_get_cipher_ctx(btmp, &ctx);
216 217
		keylen=EVP_CIPHER_key_length(evp_cipher);
		ivlen=EVP_CIPHER_iv_length(evp_cipher);
218 219
		if (RAND_bytes(key,keylen) <= 0)
			goto err;
220
		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
221
		if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
222
		EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1);
223

224 225 226 227 228 229
		if (ivlen > 0) {
			if (xalg->parameter == NULL) 
						xalg->parameter=ASN1_TYPE_new();
			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
								       goto err;
		}
230 231 232

		/* Lets do the pub key stuff :-) */
		max=0;
B
stack.  
Ben Laurie 已提交
233
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
234
			{
B
stack.  
Ben Laurie 已提交
235
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
236 237 238 239 240
			if (ri->cert == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
				goto err;
				}
241 242
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_size(pkey);
243
			EVP_PKEY_free(pkey);
244 245
			if (max < jj) max=jj;
			}
246
		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
247 248 249 250
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
B
stack.  
Ben Laurie 已提交
251
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
252
			{
B
stack.  
Ben Laurie 已提交
253
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
254 255
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
256
			EVP_PKEY_free(pkey);
257 258 259
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
260
				OPENSSL_free(tmp);
261 262
				goto err;
				}
263
			M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
264
			}
265
		OPENSSL_free(tmp);
266
		OPENSSL_cleanse(key, keylen);
267 268 269 270 271

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
272
		btmp=NULL;
273 274
		}

275 276
	if (bio == NULL)
		{
D
 
Dr. Stephen Henson 已提交
277
		if (PKCS7_is_detached(p7))
278
			bio=BIO_new(BIO_s_null());
279 280 281
		else if (os && os->length > 0)
			bio = BIO_new_mem_buf(os->data, os->length);
		if(bio == NULL)
282
			{
283 284
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
285
			}
286
		}
287
	BIO_push(out,bio);
288 289 290 291 292 293 294 295 296 297
	bio=NULL;
	if (0)
		{
err:
		if (out != NULL)
			BIO_free_all(out);
		if (btmp != NULL)
			BIO_free_all(btmp);
		out=NULL;
		}
298
	return(out);
299 300 301
	}

/* int */
302
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
303 304 305
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
306
	unsigned char *tmp=NULL;
307 308
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
B
Ben Laurie 已提交
309 310
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
311 312
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
B
Stack.  
Ben Laurie 已提交
313
	STACK_OF(X509_ALGOR) *md_sk=NULL;
B
stack.  
Ben Laurie 已提交
314
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
315 316 317 318 319 320 321 322 323
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
324
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
325 326 327 328 329 330 331
		md_sk=p7->d.sign->md_algs;
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
332
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
333 334
		if (evp_cipher == NULL)
			{
335
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
336 337 338 339 340 341 342 343
			goto err;
			}
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		enc_alg=p7->d.enveloped->enc_data->algorithm;
		data_body=p7->d.enveloped->enc_data->enc_data;
344
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
345 346
		if (evp_cipher == NULL)
			{
347
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
348 349 350 351 352
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
	default:
353
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
354 355 356 357 358 359
	        goto err;
		}

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
B
Stack.  
Ben Laurie 已提交
360
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
361
			{
B
Stack.  
Ben Laurie 已提交
362
			xa=sk_X509_ALGOR_value(md_sk,i);
363 364
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
365
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
366 367 368 369
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
370
			evp_md=EVP_get_digestbynid(j);
371 372
			if (evp_md == NULL)
				{
373
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
			btmp=NULL;
			}
		}

	if (evp_cipher != NULL)
		{
#if 0
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char *p;
		int keylen,ivlen;
		int max;
		X509_OBJECT ret;
#endif
		int jj;

		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
			{
400
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
401 402 403 404 405 406
			goto err;
			}

		/* It was encrypted, we need to decrypt the secret key
		 * with the private key */

407 408
		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
409 410
		 */

B
stack.  
Ben Laurie 已提交
411 412
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
413 414
			if(!X509_NAME_cmp(ri->issuer_and_serial->issuer,
					pcert->cert_info->issuer) &&
415
			     !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber,
416
					ri->issuer_and_serial->serial)) break;
417
			ri=NULL;
418 419 420 421
		}
		if (ri == NULL) {
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				 PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
422
			goto err;
423
		}
424 425

		jj=EVP_PKEY_size(pkey);
426
		tmp=(unsigned char *)OPENSSL_malloc(jj+10);
427 428
		if (tmp == NULL)
			{
429
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
430 431 432
			goto err;
			}

433 434
		jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key),
			M_ASN1_STRING_length(ri->enc_key), pkey);
435 436
		if (jj <= 0)
			{
437
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB);
438 439 440 441 442
			goto err;
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
443
		EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0);
444
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
445
			goto err;
446

447
		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
D
 
Dr. Stephen Henson 已提交
448
			/* Some S/MIME clients don't use the same key
449 450 451
			 * and effective key length. The key length is
			 * determined by the size of the decrypted RSA key.
			 */
D
 
Dr. Stephen Henson 已提交
452
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
B
Bodo Möller 已提交
453
				{
454
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
455
					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
456
				goto err;
B
Bodo Möller 已提交
457
				}
D
 
Dr. Stephen Henson 已提交
458
		} 
459
		EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0);
460

461
		OPENSSL_cleanse(tmp,jj);
462 463 464 465 466 467 468 469 470

		if (out == NULL)
			out=etmp;
		else
			BIO_push(out,etmp);
		etmp=NULL;
		}

#if 1
D
 
Dr. Stephen Henson 已提交
471
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
472 473 474 475 476
		{
		bio=in_bio;
		}
	else 
		{
477
#if 0
478 479 480 481 482 483 484 485
		bio=BIO_new(BIO_s_mem());
		/* We need to set this so that when we have read all
		 * the data, the encrypt BIO, if present, will read
		 * EOF and encode the last few bytes */
		BIO_set_mem_eof_return(bio,0);

		if (data_body->length > 0)
			BIO_write(bio,(char *)data_body->data,data_body->length);
486 487 488 489 490 491 492 493
#else
		if (data_body->length > 0)
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
		else {
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
		}
#endif
494 495 496 497 498 499
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
500
err:
501 502 503 504 505 506 507
		if (out != NULL) BIO_free_all(out);
		if (btmp != NULL) BIO_free_all(btmp);
		if (etmp != NULL) BIO_free_all(etmp);
		if (bio != NULL) BIO_free_all(bio);
		out=NULL;
		}
	if (tmp != NULL)
508
		OPENSSL_free(tmp);
509
	return(out);
510 511
	}

512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
	{
	for (;;)
		{
		bio=BIO_find_type(bio,BIO_TYPE_MD);
		if (bio == NULL)
			{
			PKCS7err(PKCS7_F_FIND_DIGEST,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
			return NULL;	
			}
		BIO_get_md_ctx(bio,pmd);
		if (*pmd == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR);
			return NULL;
			}	
		if (EVP_MD_CTX_type(*pmd) == nid)
			return bio;
		bio=BIO_next(bio);
		}
	return NULL;
	}

U
Ulf Möller 已提交
535
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
536 537 538 539 540 541 542 543
	{
	int ret=0;
	int i,j;
	BIO *btmp;
	BUF_MEM *buf_mem=NULL;
	BUF_MEM *buf=NULL;
	PKCS7_SIGNER_INFO *si;
	EVP_MD_CTX *mdc,ctx_tmp;
B
Ben Laurie 已提交
544
	STACK_OF(X509_ATTRIBUTE) *sk;
B
Stack.  
Ben Laurie 已提交
545
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
546
	ASN1_OCTET_STRING *os=NULL;
547

548
	EVP_MD_CTX_init(&ctx_tmp);
549 550 551 552 553
	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
554 555 556
	case NID_pkcs7_signedAndEnveloped:
		/* XXXXXXXXXXXXXXXX */
		si_sk=p7->d.signed_and_enveloped->signer_info;
557
		os=M_ASN1_OCTET_STRING_new();
558 559
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
		break;
560 561
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
562
		os=M_ASN1_OCTET_STRING_new();
563 564
		p7->d.enveloped->enc_data->enc_data=os;
		break;
565
	case NID_pkcs7_signed:
566
		si_sk=p7->d.sign->signer_info;
567
		os=PKCS7_get_octet_string(p7->d.sign->contents);
568
		/* If detached data then the content is excluded */
569
		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
570
			M_ASN1_OCTET_STRING_free(os);
571 572
			p7->d.sign->contents->d.data = NULL;
		}
573
		break;
574 575 576 577 578 579 580 581 582 583 584

	case NID_pkcs7_digest:
		os=PKCS7_get_octet_string(p7->d.digest->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
			{
			M_ASN1_OCTET_STRING_free(os);
			p7->d.digest->contents->d.data = NULL;
			}
		break;

585
		}
586

587 588
	if (si_sk != NULL)
		{
589 590 591 592 593
		if ((buf=BUF_MEM_new()) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
			goto err;
			}
B
Stack.  
Ben Laurie 已提交
594
		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
595
			{
B
Stack.  
Ben Laurie 已提交
596
			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
597 598 599
			if (si->pkey == NULL) continue;

			j=OBJ_obj2nid(si->digest_alg->algorithm);
600 601

			btmp=bio;
602 603 604 605 606 607

			btmp = PKCS7_find_digest(&mdc, btmp, j);

			if (btmp == NULL)
				goto err;

608 609
			/* We now have the EVP_MD_CTX, lets do the
			 * signing. */
D
 
Dr. Stephen Henson 已提交
610
			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
611
			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
612 613
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
614
				goto err;
615
				}
616 617

			sk=si->auth_attr;
618 619 620

			/* If there are attributes, we add the digest
			 * attribute and only sign the attributes */
B
Ben Laurie 已提交
621
			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
622
				{
623 624
				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
				unsigned int md_len, alen;
625 626
				ASN1_OCTET_STRING *digest;
				ASN1_UTCTIME *sign_time;
B
Ben Laurie 已提交
627
				const EVP_MD *md_tmp;
628

D
 
Dr. Stephen Henson 已提交
629 630 631 632 633 634 635 636 637
				/* Add signing time if not already present */
				if (!PKCS7_get_signed_attribute(si,
							NID_pkcs9_signingTime))
					{
					sign_time=X509_gmtime_adj(NULL,0);
					PKCS7_add_signed_attribute(si,
						NID_pkcs9_signingTime,
						V_ASN1_UTCTIME,sign_time);
					}
638 639

				/* Add digest */
640
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
D
 
Dr. Stephen Henson 已提交
641
				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
642 643
				digest=M_ASN1_OCTET_STRING_new();
				M_ASN1_OCTET_STRING_set(digest,md_data,md_len);
644 645
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_messageDigest,
646
					V_ASN1_OCTET_STRING,digest);
647

648
				/* Now sign the attributes */
D
 
Dr. Stephen Henson 已提交
649
				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
650
				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
651
							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
652 653 654
				if(!abuf) goto err;
				EVP_SignUpdate(&ctx_tmp,abuf,alen);
				OPENSSL_free(abuf);
655 656
				}

657
#ifndef OPENSSL_NO_DSA
658 659
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();
660
#endif
B
Bodo Möller 已提交
661
#ifndef OPENSSL_NO_ECDSA
662
 			if (si->pkey->type == EVP_PKEY_EC)
B
Bodo Möller 已提交
663 664
 				ctx_tmp.digest=EVP_ecdsa();
#endif
665

666
			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
667
				(unsigned int *)&buf->length,si->pkey))
668 669
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
670
				goto err;
671
				}
672 673 674
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
675
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
676 677 678 679
				goto err;
				}
			}
		}
680 681 682 683 684 685 686 687 688 689
	else if (i == NID_pkcs7_digest)
		{
		unsigned char md_data[EVP_MAX_MD_SIZE];
		unsigned int md_len;
		if (!PKCS7_find_digest(&mdc, bio,
				OBJ_obj2nid(p7->d.digest->md->algorithm)))
			goto err;
		EVP_DigestFinal_ex(mdc,md_data,&md_len);
		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
		}
690

D
 
Dr. Stephen Henson 已提交
691
	if (!PKCS7_is_detached(p7))
692 693 694 695 696 697 698 699
		{
		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
		if (btmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
			goto err;
			}
		BIO_get_mem_ptr(btmp,&buf_mem);
700 701 702 703 704 705 706 707
		/* Mark the BIO read only then we can use its copy of the data
		 * instead of making an extra copy.
		 */
		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
		BIO_set_mem_eof_return(btmp, 0);
		os->data = (unsigned char *)buf_mem->data;
		os->length = buf_mem->length;
#if 0
708
		M_ASN1_OCTET_STRING_set(os,
709
			(unsigned char *)buf_mem->data,buf_mem->length);
710
#endif
711
		}
712 713
	ret=1;
err:
714
	EVP_MD_CTX_cleanup(&ctx_tmp);
715 716 717 718
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}

U
Ulf Möller 已提交
719 720
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
721 722
	{
	PKCS7_ISSUER_AND_SERIAL *ias;
723
	int ret=0,i;
B
Ben Laurie 已提交
724
	STACK_OF(X509) *cert;
725 726
	X509 *x509;

727 728 729 730 731 732 733 734 735 736 737 738 739
	if (PKCS7_type_is_signed(p7))
		{
		cert=p7->d.sign->cert;
		}
	else if (PKCS7_type_is_signedAndEnveloped(p7))
		{
		cert=p7->d.signed_and_enveloped->cert;
		}
	else
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_WRONG_PKCS7_TYPE);
		goto err;
		}
740
	/* XXXXXXXXXXXXXXXXXXXXXXX */
741 742
	ias=si->issuer_and_serial;

743
	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
744 745 746 747 748 749 750 751 752

	/* were we able to find the cert in passed to us */
	if (x509 == NULL)
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_CERTIFICATE);
		goto err;
		}

	/* Lets verify */
753 754 755 756 757
	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
		goto err;
		}
758
	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
759
	i=X509_verify_cert(ctx);
760 761 762
	if (i <= 0) 
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
763
		X509_STORE_CTX_cleanup(ctx);
764 765
		goto err;
		}
766 767
	X509_STORE_CTX_cleanup(ctx);

768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783
	return PKCS7_signatureVerify(bio, p7, si, x509);
	err:
	return ret;
	}

int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
								X509 *x509)
	{
	ASN1_OCTET_STRING *os;
	EVP_MD_CTX mdc_tmp,*mdc;
	int ret=0,i;
	int md_type;
	STACK_OF(X509_ATTRIBUTE) *sk;
	BIO *btmp;
	EVP_PKEY *pkey;

784 785
	EVP_MD_CTX_init(&mdc_tmp);

786 787 788 789 790 791 792
	if (!PKCS7_type_is_signed(p7) && 
				!PKCS7_type_is_signedAndEnveloped(p7)) {
		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
						PKCS7_R_WRONG_PKCS7_TYPE);
		goto err;
	}

793 794 795 796 797 798 799 800
	md_type=OBJ_obj2nid(si->digest_alg->algorithm);

	btmp=bio;
	for (;;)
		{
		if ((btmp == NULL) ||
			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
			{
801 802
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
803 804 805 806 807
			goto err;
			}
		BIO_get_md_ctx(btmp,&mdc);
		if (mdc == NULL)
			{
808
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
B
Bodo Möller 已提交
809
							ERR_R_INTERNAL_ERROR);
810 811
			goto err;
			}
812
		if (EVP_MD_CTX_type(mdc) == md_type)
813
			break;
814 815 816 817 818
		/* Workaround for some broken clients that put the signature
		 * OID instead of the digest OID in digest_alg->algorithm
		 */
		if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
			break;
D
 
Dr. Stephen Henson 已提交
819
		btmp=BIO_next(btmp);
820 821
		}

822 823
	/* mdc is the digest ctx that we want, unless there are attributes,
	 * in which case the digest is the signed attributes */
D
 
Dr. Stephen Henson 已提交
824
	EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
825 826

	sk=si->auth_attr;
B
Ben Laurie 已提交
827
	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
828
		{
829 830
		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
                unsigned int md_len, alen;
831 832
		ASN1_OCTET_STRING *message_digest;

D
 
Dr. Stephen Henson 已提交
833
		EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
834 835 836
		message_digest=PKCS7_digest_from_attributes(sk);
		if (!message_digest)
			{
837 838
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
839 840
			goto err;
			}
841
		if ((message_digest->length != (int)md_len) ||
842 843 844 845 846 847 848 849 850 851
			(memcmp(message_digest->data,md_dat,md_len)))
			{
#if 0
{
int ii;
for (ii=0; ii<message_digest->length; ii++)
	printf("%02X",message_digest->data[ii]); printf(" sent\n");
for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
}
#endif
852 853
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
							PKCS7_R_DIGEST_FAILURE);
854 855 856 857
			ret= -1;
			goto err;
			}

D
 
Dr. Stephen Henson 已提交
858
		EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL);
859 860

		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
861
						ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
862 863 864
		EVP_VerifyUpdate(&mdc_tmp, abuf, alen);

		OPENSSL_free(abuf);
865 866 867
		}

	os=si->enc_digest;
868
	pkey = X509_get_pubkey(x509);
869 870 871 872 873
	if (!pkey)
		{
		ret = -1;
		goto err;
		}
874
#ifndef OPENSSL_NO_DSA
875
	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
876
#endif
B
Bodo Möller 已提交
877
#ifndef OPENSSL_NO_ECDSA
878
	if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
B
Bodo Möller 已提交
879
#endif
880

881 882
	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
	EVP_PKEY_free(pkey);
883 884
	if (i <= 0)
		{
885 886
		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
						PKCS7_R_SIGNATURE_FAILURE);
887 888 889 890 891 892
		ret= -1;
		goto err;
		}
	else
		ret=1;
err:
893
	EVP_MD_CTX_cleanup(&mdc_tmp);
894 895 896
	return(ret);
	}

U
Ulf Möller 已提交
897
PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
898
	{
B
stack.  
Ben Laurie 已提交
899
	STACK_OF(PKCS7_RECIP_INFO) *rsk;
900 901 902 903 904 905
	PKCS7_RECIP_INFO *ri;
	int i;

	i=OBJ_obj2nid(p7->type);
	if (i != NID_pkcs7_signedAndEnveloped) return(NULL);
	rsk=p7->d.signed_and_enveloped->recipientinfo;
B
stack.  
Ben Laurie 已提交
906 907 908
	ri=sk_PKCS7_RECIP_INFO_value(rsk,0);
	if (sk_PKCS7_RECIP_INFO_num(rsk) <= idx) return(NULL);
	ri=sk_PKCS7_RECIP_INFO_value(rsk,idx);
909 910 911
	return(ri->issuer_and_serial);
	}

U
Ulf Möller 已提交
912
ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
913 914 915 916
	{
	return(get_attribute(si->auth_attr,nid));
	}

U
Ulf Möller 已提交
917
ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
918 919 920 921
	{
	return(get_attribute(si->unauth_attr,nid));
	}

B
Ben Laurie 已提交
922
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
923 924 925 926 927 928
	{
	int i;
	X509_ATTRIBUTE *xa;
	ASN1_OBJECT *o;

	o=OBJ_nid2obj(nid);
929
	if (!o || !sk) return(NULL);
B
Ben Laurie 已提交
930
	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
931
		{
B
Ben Laurie 已提交
932
		xa=sk_X509_ATTRIBUTE_value(sk,i);
933 934
		if (OBJ_cmp(xa->object,o) == 0)
			{
D
 
Dr. Stephen Henson 已提交
935
			if (!xa->single && sk_ASN1_TYPE_num(xa->value.set))
B
Ben Laurie 已提交
936
				return(sk_ASN1_TYPE_value(xa->value.set,0));
937 938 939 940 941 942 943
			else
				return(NULL);
			}
		}
	return(NULL);
	}

B
Ben Laurie 已提交
944
ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
945
{
946
	ASN1_TYPE *astype;
947 948 949
	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
	return astype->value.octet_string;
}
950

B
Ben Laurie 已提交
951 952
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
				STACK_OF(X509_ATTRIBUTE) *sk)
953 954 955 956
	{
	int i;

	if (p7si->auth_attr != NULL)
B
Ben Laurie 已提交
957 958 959
		sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
	p7si->auth_attr=sk_X509_ATTRIBUTE_dup(sk);
	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
960
		{
B
Ben Laurie 已提交
961 962 963
		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
		    == NULL)
964 965 966 967 968
			return(0);
		}
	return(1);
	}

B
Ben Laurie 已提交
969
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
970 971 972 973
	{
	int i;

	if (p7si->unauth_attr != NULL)
B
Ben Laurie 已提交
974 975 976 977
		sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr,
					   X509_ATTRIBUTE_free);
	p7si->unauth_attr=sk_X509_ATTRIBUTE_dup(sk);
	for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++)
978
		{
B
Ben Laurie 已提交
979 980 981
		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
                        X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
		    == NULL)
982 983 984 985 986
			return(0);
		}
	return(1);
	}

U
Ulf Möller 已提交
987
int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
988
	     void *value)
989 990 991 992
	{
	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
	}

U
Ulf Möller 已提交
993
int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
994
	     void *value)
995 996 997 998
	{
	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
	}

B
Ben Laurie 已提交
999 1000
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
			 void *value)
1001 1002 1003 1004 1005
	{
	X509_ATTRIBUTE *attr=NULL;

	if (*sk == NULL)
		{
1006
		*sk = sk_X509_ATTRIBUTE_new_null();
1007 1008
new_attrib:
		attr=X509_ATTRIBUTE_create(nid,atrtype,value);
B
Ben Laurie 已提交
1009
		sk_X509_ATTRIBUTE_push(*sk,attr);
1010 1011 1012 1013 1014
		}
	else
		{
		int i;

B
Ben Laurie 已提交
1015
		for (i=0; i<sk_X509_ATTRIBUTE_num(*sk); i++)
1016
			{
B
Ben Laurie 已提交
1017
			attr=sk_X509_ATTRIBUTE_value(*sk,i);
1018 1019 1020 1021
			if (OBJ_obj2nid(attr->object) == nid)
				{
				X509_ATTRIBUTE_free(attr);
				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
B
Ben Laurie 已提交
1022
				sk_X509_ATTRIBUTE_set(*sk,i,attr);
1023 1024 1025 1026 1027 1028 1029 1030 1031
				goto end;
				}
			}
		goto new_attrib;
		}
end:
	return(1);
	}