pk7_doit.c 25.7 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
		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
219
		if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
220 221 222 223 224 225
		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
			goto err;
		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
			goto err;
		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
			goto err;
226

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

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

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
275
		btmp=NULL;
276 277
		}

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

/* int */
305
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
306 307 308
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
309
	unsigned char *tmp=NULL;
310 311
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
B
Ben Laurie 已提交
312 313
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
314 315
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
B
Stack.  
Ben Laurie 已提交
316
	STACK_OF(X509_ALGOR) *md_sk=NULL;
B
stack.  
Ben Laurie 已提交
317
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
318 319 320 321 322 323 324 325 326
	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:
327
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
328 329 330 331 332 333 334
		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;
335
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
336 337
		if (evp_cipher == NULL)
			{
338
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
339 340 341 342 343 344 345 346
			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;
347
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
348 349
		if (evp_cipher == NULL)
			{
350
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
351 352 353 354 355
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
	default:
356
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
357 358 359 360 361 362
	        goto err;
		}

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

			j=OBJ_obj2nid(xa->algorithm);
373
			evp_md=EVP_get_digestbynid(j);
374 375
			if (evp_md == NULL)
				{
376
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
				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)
			{
403
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
404 405 406 407 408 409
			goto err;
			}

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

410 411
		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
412 413
		 */

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

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

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

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
446 447
		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
			goto err;
448
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
449
			goto err;
450

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

466
		OPENSSL_cleanse(tmp,jj);
467 468 469 470 471 472 473 474 475

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

#if 1
D
 
Dr. Stephen Henson 已提交
476
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
477 478 479 480 481
		{
		bio=in_bio;
		}
	else 
		{
482
#if 0
483 484 485 486 487 488 489 490
		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);
491 492 493 494 495 496 497 498
#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
499 500 501 502 503 504
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
505
err:
506 507 508 509 510 511 512
		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)
513
		OPENSSL_free(tmp);
514
	return(out);
515 516
	}

517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
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 已提交
540
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
541 542 543 544 545 546 547 548
	{
	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 已提交
549
	STACK_OF(X509_ATTRIBUTE) *sk;
B
Stack.  
Ben Laurie 已提交
550
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
551
	ASN1_OCTET_STRING *os=NULL;
552

553
	EVP_MD_CTX_init(&ctx_tmp);
554 555 556 557 558
	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

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

	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;

590
		}
591

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

			j=OBJ_obj2nid(si->digest_alg->algorithm);
605 606

			btmp=bio;
607 608 609 610 611 612

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

			if (btmp == NULL)
				goto err;

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

			sk=si->auth_attr;
623 624 625

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

D
 
Dr. Stephen Henson 已提交
634 635 636 637 638 639 640 641 642
				/* 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);
					}
643 644

				/* Add digest */
645
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
D
 
Dr. Stephen Henson 已提交
646
				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
647 648
				digest=M_ASN1_OCTET_STRING_new();
				M_ASN1_OCTET_STRING_set(digest,md_data,md_len);
649 650
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_messageDigest,
651
					V_ASN1_OCTET_STRING,digest);
652

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

662
#ifndef OPENSSL_NO_DSA
663 664
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();
665
#endif
B
Bodo Möller 已提交
666
#ifndef OPENSSL_NO_ECDSA
667
 			if (si->pkey->type == EVP_PKEY_EC)
B
Bodo Möller 已提交
668 669
 				ctx_tmp.digest=EVP_ecdsa();
#endif
670

671
			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
672
				(unsigned int *)&buf->length,si->pkey))
673 674
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
675
				goto err;
676
				}
677 678 679
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
680
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
681 682 683 684
				goto err;
				}
			}
		}
685 686 687 688 689 690 691 692 693 694
	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);
		}
695

D
 
Dr. Stephen Henson 已提交
696
	if (!PKCS7_is_detached(p7))
697 698 699 700 701 702 703 704
		{
		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);
705 706 707 708 709 710 711 712
		/* 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
713
		M_ASN1_OCTET_STRING_set(os,
714
			(unsigned char *)buf_mem->data,buf_mem->length);
715
#endif
716
		}
717 718
	ret=1;
err:
719
	EVP_MD_CTX_cleanup(&ctx_tmp);
720 721 722 723
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}

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

732 733 734 735 736 737 738 739 740 741 742 743 744
	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;
		}
745
	/* XXXXXXXXXXXXXXXXXXXXXXX */
746 747
	ias=si->issuer_and_serial;

748
	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
749 750 751 752 753 754 755 756 757

	/* 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 */
758 759 760 761 762
	if(!X509_STORE_CTX_init(ctx,cert_store,x509,cert))
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
		goto err;
		}
763
	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_SMIME_SIGN);
764
	i=X509_verify_cert(ctx);
765 766 767
	if (i <= 0) 
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
768
		X509_STORE_CTX_cleanup(ctx);
769 770
		goto err;
		}
771 772
	X509_STORE_CTX_cleanup(ctx);

773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
	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;

789 790
	EVP_MD_CTX_init(&mdc_tmp);

791 792 793 794 795 796 797
	if (!PKCS7_type_is_signed(p7) && 
				!PKCS7_type_is_signedAndEnveloped(p7)) {
		PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
						PKCS7_R_WRONG_PKCS7_TYPE);
		goto err;
	}

798 799 800 801 802 803 804 805
	md_type=OBJ_obj2nid(si->digest_alg->algorithm);

	btmp=bio;
	for (;;)
		{
		if ((btmp == NULL) ||
			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
			{
806 807
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
808 809 810 811 812
			goto err;
			}
		BIO_get_md_ctx(btmp,&mdc);
		if (mdc == NULL)
			{
813
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
B
Bodo Möller 已提交
814
							ERR_R_INTERNAL_ERROR);
815 816
			goto err;
			}
817
		if (EVP_MD_CTX_type(mdc) == md_type)
818
			break;
819 820 821 822 823
		/* 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 已提交
824
		btmp=BIO_next(btmp);
825 826
		}

827 828
	/* 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 已提交
829
	EVP_MD_CTX_copy_ex(&mdc_tmp,mdc);
830 831

	sk=si->auth_attr;
B
Ben Laurie 已提交
832
	if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
833
		{
834 835
		unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL;
                unsigned int md_len, alen;
836 837
		ASN1_OCTET_STRING *message_digest;

D
 
Dr. Stephen Henson 已提交
838
		EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len);
839 840 841
		message_digest=PKCS7_digest_from_attributes(sk);
		if (!message_digest)
			{
842 843
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
					PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
844 845
			goto err;
			}
846
		if ((message_digest->length != (int)md_len) ||
847 848 849 850 851 852 853 854 855 856
			(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
857 858
			PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY,
							PKCS7_R_DIGEST_FAILURE);
859 860 861 862
			ret= -1;
			goto err;
			}

D
 
Dr. Stephen Henson 已提交
863
		EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL);
864 865

		alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf,
866
						ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY));
867 868 869
		EVP_VerifyUpdate(&mdc_tmp, abuf, alen);

		OPENSSL_free(abuf);
870 871 872
		}

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

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

U
Ulf Möller 已提交
902
PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
903
	{
B
stack.  
Ben Laurie 已提交
904
	STACK_OF(PKCS7_RECIP_INFO) *rsk;
905 906 907 908 909 910
	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 已提交
911 912 913
	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);
914 915 916
	return(ri->issuer_and_serial);
	}

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

U
Ulf Möller 已提交
922
ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
923 924 925 926
	{
	return(get_attribute(si->unauth_attr,nid));
	}

B
Ben Laurie 已提交
927
static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
928 929 930 931 932 933
	{
	int i;
	X509_ATTRIBUTE *xa;
	ASN1_OBJECT *o;

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

B
Ben Laurie 已提交
949
ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
950
{
951
	ASN1_TYPE *astype;
952 953 954
	if(!(astype = get_attribute(sk, NID_pkcs9_messageDigest))) return NULL;
	return astype->value.octet_string;
}
955

B
Ben Laurie 已提交
956 957
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
				STACK_OF(X509_ATTRIBUTE) *sk)
958 959 960 961
	{
	int i;

	if (p7si->auth_attr != NULL)
B
Ben Laurie 已提交
962 963 964
		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++)
965
		{
B
Ben Laurie 已提交
966 967 968
		if ((sk_X509_ATTRIBUTE_set(p7si->auth_attr,i,
			X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
		    == NULL)
969 970 971 972 973
			return(0);
		}
	return(1);
	}

B
Ben Laurie 已提交
974
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK_OF(X509_ATTRIBUTE) *sk)
975 976 977 978
	{
	int i;

	if (p7si->unauth_attr != NULL)
B
Ben Laurie 已提交
979 980 981 982
		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++)
983
		{
B
Ben Laurie 已提交
984 985 986
		if ((sk_X509_ATTRIBUTE_set(p7si->unauth_attr,i,
                        X509_ATTRIBUTE_dup(sk_X509_ATTRIBUTE_value(sk,i))))
		    == NULL)
987 988 989 990 991
			return(0);
		}
	return(1);
	}

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

U
Ulf Möller 已提交
998
int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
999
	     void *value)
1000 1001 1002 1003
	{
	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
	}

B
Ben Laurie 已提交
1004 1005
static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
			 void *value)
1006 1007 1008 1009 1010
	{
	X509_ATTRIBUTE *attr=NULL;

	if (*sk == NULL)
		{
1011
		*sk = sk_X509_ATTRIBUTE_new_null();
1012 1013
new_attrib:
		attr=X509_ATTRIBUTE_create(nid,atrtype,value);
B
Ben Laurie 已提交
1014
		sk_X509_ATTRIBUTE_push(*sk,attr);
1015 1016 1017 1018 1019
		}
	else
		{
		int i;

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