pk7_doit.c 22.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

65
static int add_attribute(STACK **sk, int nid, int atrtype, void *value);
66 67 68
static ASN1_TYPE *get_attribute(STACK *sk, int nid);

#if 1
U
Ulf Möller 已提交
69
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
70 71
	{
	int i,j;
72
	BIO *out=NULL,*btmp=NULL;
73
	X509_ALGOR *xa;
B
Ben Laurie 已提交
74 75
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
76 77 78 79
	STACK *md_sk=NULL,*rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	EVP_PKEY *pkey;
80 81 82 83 84 85 86

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

	switch (i)
		{
	case NID_pkcs7_signed:
87 88 89 90 91 92 93
		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;
		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(p7->d.signed_and_enveloped->enc_data->algorithm->algorithm)));
		if (evp_cipher == NULL)
94
			{
95 96 97 98 99
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		break;
100 101 102 103 104 105 106 107 108 109
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(p7->d.enveloped->enc_data->algorithm->algorithm)));
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
110 111 112 113 114 115 116 117 118 119
	default:
		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	if (md_sk != NULL)
		{
		for (i=0; i<sk_num(md_sk); i++)
			{
			xa=(X509_ALGOR *)sk_value(md_sk,i);
120 121 122 123 124
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
				goto err;
				}
125 126 127 128 129 130 131 132 133 134 135 136 137 138

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbyname(OBJ_nid2sn(j));
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
139
			btmp=NULL;
140 141
			}
		}
142 143 144 145 146 147 148 149 150

	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;

151 152 153 154 155
		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
			goto err;
			}
156 157 158 159 160 161 162 163 164 165
		keylen=EVP_CIPHER_key_length(evp_cipher);
		ivlen=EVP_CIPHER_iv_length(evp_cipher);

		if (ivlen > 0)
			{
			ASN1_OCTET_STRING *os;

			RAND_bytes(iv,ivlen);
			os=ASN1_OCTET_STRING_new();
			ASN1_OCTET_STRING_set(os,iv,ivlen);
166 167 168 169
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX this needs to change */
			if (xalg->parameter == NULL)
				xalg->parameter=ASN1_TYPE_new();
			ASN1_TYPE_set(xalg->parameter,V_ASN1_OCTET_STRING,
170
				(char *)os);
171
			}
172 173 174 175 176 177 178
		RAND_bytes(key,keylen);

		/* Lets do the pub key stuff :-) */
		max=0;
		for (i=0; i<sk_num(rsk); i++)
			{
			ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
179 180 181 182 183
			if (ri->cert == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
				goto err;
				}
184 185
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_size(pkey);
186
			EVP_PKEY_free(pkey);
187 188
			if (max < jj) max=jj;
			}
189 190 191 192 193
		if ((tmp=(unsigned char *)Malloc(max)) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
194 195 196 197 198
		for (i=0; i<sk_num(rsk); i++)
			{
			ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
199
			EVP_PKEY_free(pkey);
200 201 202 203 204 205
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
				Free(tmp);
				goto err;
				}
206 207
			ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
			}
208
		Free(tmp);
209 210 211 212 213 214 215

		BIO_set_cipher(btmp,evp_cipher,key,iv,1);

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
216
		btmp=NULL;
217 218 219
		}

	if (bio == NULL) /* ??????????? */
220 221 222 223 224 225
		{
		if (p7->detached)
			bio=BIO_new(BIO_s_null());
		else
			{
			bio=BIO_new(BIO_s_mem());
226 227 228 229 230
			/* 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);

231 232 233 234 235 236 237
			if (PKCS7_type_is_signed(p7) &&
				PKCS7_type_is_data(p7->d.sign->contents))
				{
				ASN1_OCTET_STRING *os;

				os=p7->d.sign->contents->d.data;
				if (os->length > 0)
238 239
					BIO_write(bio,(char *)os->data,
						os->length);
240 241 242 243
				}
			}
		}
	BIO_push(out,bio);
244 245 246 247 248 249 250 251 252 253
	bio=NULL;
	if (0)
		{
err:
		if (out != NULL)
			BIO_free_all(out);
		if (btmp != NULL)
			BIO_free_all(btmp);
		out=NULL;
		}
254
	return(out);
255 256 257
	}

/* int */
U
Ulf Möller 已提交
258 259
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio,
	     X509_STORE *xs)
260 261 262 263 264 265
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
	char *tmp=NULL;
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
B
Ben Laurie 已提交
266 267
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 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 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
	STACK *md_sk=NULL,*rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
/*	EVP_PKEY *pkey; */
#if 0
	X509_STORE_CTX s_ctx;
#endif

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

	switch (i)
		{
	case NID_pkcs7_signed:
		data_body=p7->d.sign->contents->d.data;
		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;
		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			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;
		evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)));
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
		for (i=0; i<sk_num(md_sk); i++)
			{
			xa=(X509_ALGOR *)sk_value(md_sk,i);
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB);
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbyname(OBJ_nid2sn(j));
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				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)
			{
			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB);
			goto err;
			}

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

		/* We need to find a private key for one of the people in the
		 * recipentinfo list */
		if (rsk == NULL)
			return(NULL);

		ri=(PKCS7_RECIP_INFO *)sk_value(rsk,0);
#if 0
		X509_STORE_CTX_init(&s_ctx,xs,NULL,NULL);
		for (i=0; i<sk_num(rsk); i++)
			{
			ri=(PKCS7_RECIP_INFO *)sk_value(rsk,i);
			uf (X509_STORE_get_by_issuer_serial(&s_ctx,
				X509_LU_PKEY,
				ri->issuer_and_serial->issuer,
				ri->issuer_and_serial->serial,
				&ret))
				break;
			ri=NULL;
			}
		if (ri == NULL) return(NULL);	
		pkey=ret.data.pkey;
#endif
		if (pkey == NULL)
			{
			return(NULL);
			}

		jj=EVP_PKEY_size(pkey);
		tmp=Malloc(jj+10);
		if (tmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_MALLOC_FAILURE);
			goto err;
			}

		jj=EVP_PKEY_decrypt((unsigned char *)tmp,
			ASN1_STRING_data(ri->enc_key),
			ASN1_STRING_length(ri->enc_key),
			pkey);
		if (jj <= 0)
			{
			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_EVP_LIB);
			goto err;
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
		EVP_CipherInit(evp_ctx,evp_cipher,NULL,NULL,0);
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
			return(NULL);

		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx))
			{
			PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
			goto err;
			}
		EVP_CipherInit(evp_ctx,NULL,(unsigned char *)tmp,NULL,0);

		memset(tmp,0,jj);

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

#if 1
	if (p7->detached || (in_bio != NULL))
		{
		bio=in_bio;
		}
	else 
		{
		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);
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
455
err:
456 457 458 459 460 461 462 463 464
		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)
		Free(tmp);
	return(out);
465
	}
466
#endif
467

U
Ulf Möller 已提交
468
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
469 470 471 472 473 474 475 476
	{
	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;
477
	STACK *sk,*si_sk=NULL;
478 479
	unsigned char *p,*pp=NULL;
	int x;
480
	ASN1_OCTET_STRING *os=NULL;
481 482 483 484 485 486

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

	switch (i)
		{
487 488 489 490 491 492
	case NID_pkcs7_signedAndEnveloped:
		/* XXXXXXXXXXXXXXXX */
		si_sk=p7->d.signed_and_enveloped->signer_info;
		os=ASN1_OCTET_STRING_new();
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
		break;
493 494 495 496 497
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
		os=ASN1_OCTET_STRING_new();
		p7->d.enveloped->enc_data->enc_data=os;
		break;
498
	case NID_pkcs7_signed:
499 500
		si_sk=p7->d.sign->signer_info;
		os=p7->d.sign->contents->d.data;
501 502 503 504 505
		/* If detached data then the content is excluded */
		if(p7->detached) {
			ASN1_OCTET_STRING_free(os);
			p7->d.sign->contents->d.data = NULL;
		}
506 507
		break;
		}
508

509 510
	if (si_sk != NULL)
		{
511 512 513 514 515
		if ((buf=BUF_MEM_new()) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
			goto err;
			}
516
		for (i=0; i<sk_num(si_sk); i++)
517 518
			{
			si=(PKCS7_SIGNER_INFO *)
519
				sk_value(si_sk,i);
520 521 522
			if (si->pkey == NULL) continue;

			j=OBJ_obj2nid(si->digest_alg->algorithm);
523 524 525 526 527 528 529

			btmp=bio;
			for (;;)
				{
				if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) 
					== NULL)
					{
530
					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
531 532 533 534 535
					goto err;
					}
				BIO_get_md_ctx(btmp,&mdc);
				if (mdc == NULL)
					{
536
					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR);
537 538
					goto err;
					}
539
				if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == j)
540 541 542 543 544 545 546 547 548
					break;
				else
					btmp=btmp->next_bio;
				}
			
			/* We now have the EVP_MD_CTX, lets do the
			 * signing. */
			memcpy(&ctx_tmp,mdc,sizeof(ctx_tmp));
			if (!BUF_MEM_grow(buf,EVP_PKEY_size(si->pkey)))
549 550
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
551
				goto err;
552
				}
553 554

			sk=si->auth_attr;
555 556 557

			/* If there are attributes, we add the digest
			 * attribute and only sign the attributes */
558 559
			if ((sk != NULL) && (sk_num(sk) != 0))
				{
560 561 562 563
				unsigned char md_data[EVP_MAX_MD_SIZE];
				unsigned int md_len;
				ASN1_OCTET_STRING *digest;
				ASN1_UTCTIME *sign_time;
B
Ben Laurie 已提交
564
				const EVP_MD *md_tmp;
565 566 567 568 569

				/* Add signing time */
				sign_time=X509_gmtime_adj(NULL,0);
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_signingTime,
570
					V_ASN1_UTCTIME,sign_time);
571 572 573 574 575 576 577

				/* Add digest */
				md_tmp=EVP_MD_CTX_type(&ctx_tmp);
				EVP_DigestFinal(&ctx_tmp,md_data,&md_len);
				digest=ASN1_OCTET_STRING_new();
				ASN1_OCTET_STRING_set(digest,md_data,md_len);
				PKCS7_add_signed_attribute(si,NID_pkcs9_messageDigest,
578
					V_ASN1_OCTET_STRING,digest);
579 580 581

				/* Now sign the mess */
				EVP_SignInit(&ctx_tmp,md_tmp);
582
				x=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE,
583
					V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SET);
584
				pp=(unsigned char *)Malloc(x);
585 586
				p=pp;
				i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE,
587
					V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SET);
588 589
				EVP_SignUpdate(&ctx_tmp,pp,x);
				Free(pp);
590
				pp=NULL;
591 592
				}

593 594 595
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();

596
			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
597
				(unsigned int *)&buf->length,si->pkey))
598 599
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
600
				goto err;
601
				}
602 603 604
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
605
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
606 607 608 609 610
				goto err;
				}
			}
		}

611
	if (!p7->detached)
612 613 614 615 616 617 618 619 620 621 622 623 624 625
		{
		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);
		ASN1_OCTET_STRING_set(os,
			(unsigned char *)buf_mem->data,buf_mem->length);
		}
	if (pp != NULL) Free(pp);
	pp=NULL;

626 627 628 629 630 631
	ret=1;
err:
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}

U
Ulf Möller 已提交
632 633
int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio,
	     PKCS7 *p7, PKCS7_SIGNER_INFO *si)
634
	{
635
/*	PKCS7_SIGNED *s; */
636 637 638 639
	ASN1_OCTET_STRING *os;
	EVP_MD_CTX mdc_tmp,*mdc;
	unsigned char *pp,*p;
	PKCS7_ISSUER_AND_SERIAL *ias;
640 641
	int ret=0,i;
	int md_type;
B
Ben Laurie 已提交
642 643
	STACK *sk;
	STACK_OF(X509) *cert;
644 645
	BIO *btmp;
	X509 *x509;
646
	EVP_PKEY *pkey;
647

648 649 650 651 652 653 654 655 656 657 658 659 660
	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;
		}
661
	/* XXXXXXXXXXXXXXXXXXXXXXX */
662 663
	ias=si->issuer_and_serial;

664
	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
665 666 667 668 669 670 671 672 673

	/* 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 */
674
	X509_STORE_CTX_init(ctx,cert_store,x509,cert);
675
	i=X509_verify_cert(ctx);
676 677 678 679 680
	if (i <= 0) 
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,ERR_R_X509_LIB);
		goto err;
		}
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
	X509_STORE_CTX_cleanup(ctx);

	/* So we like 'x509', lets check the signature. */
	md_type=OBJ_obj2nid(si->digest_alg->algorithm);

	btmp=bio;
	for (;;)
		{
		if ((btmp == NULL) ||
			((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
			goto err;
			}
		BIO_get_md_ctx(btmp,&mdc);
		if (mdc == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_INTERNAL_ERROR);
			goto err;
			}
		if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == md_type)
			break;
		btmp=btmp->next_bio;	
		}

706 707
	/* mdc is the digest ctx that we want, unless there are attributes,
	 * in which case the digest is the signed attributes */
708 709 710 711 712
	memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp));

	sk=si->auth_attr;
	if ((sk != NULL) && (sk_num(sk) != 0))
		{
713
		unsigned char md_dat[EVP_MAX_MD_SIZE];
714
                unsigned int md_len;
715 716 717 718 719 720 721 722 723
		ASN1_OCTET_STRING *message_digest;

		EVP_DigestFinal(&mdc_tmp,md_dat,&md_len);
		message_digest=PKCS7_digest_from_attributes(sk);
		if (!message_digest)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
			goto err;
			}
724
		if ((message_digest->length != (int)md_len) ||
725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
			(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
			PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_DIGEST_FAILURE);
			ret= -1;
			goto err;
			}

		EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type));
741 742 743 744
		/* Note: when forming the encoding of the attributes we
		 * shouldn't reorder them or this will break the signature.
		 * This is done by using the IS_SEQUENCE flag.
		 */
745
		i=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE,
746
			V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE);
747
		pp=(unsigned char *)Malloc(i);
748 749
		p=pp;
		i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE,
750
			V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE);
751
		EVP_VerifyUpdate(&mdc_tmp,pp,i);
752

753
		Free(pp);
754 755 756
		}

	os=si->enc_digest;
757 758
	pkey = X509_get_pubkey(x509);
	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
759

760 761
	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
	EVP_PKEY_free(pkey);
762 763 764 765 766 767 768 769 770 771 772 773
	if (i <= 0)
		{
		PKCS7err(PKCS7_F_PKCS7_DATAVERIFY,PKCS7_R_SIGNATURE_FAILURE);
		ret= -1;
		goto err;
		}
	else
		ret=1;
err:
	return(ret);
	}

U
Ulf Möller 已提交
774
PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
775 776 777 778 779 780 781 782 783 784 785 786 787 788
	{
	STACK *rsk;
	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;
	ri=(PKCS7_RECIP_INFO *)sk_value(rsk,0);
	if (sk_num(rsk) <= idx) return(NULL);
	ri=(PKCS7_RECIP_INFO *)sk_value(rsk,idx);
	return(ri->issuer_and_serial);
	}

U
Ulf Möller 已提交
789
ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
790 791 792 793
	{
	return(get_attribute(si->auth_attr,nid));
	}

U
Ulf Möller 已提交
794
ASN1_TYPE *PKCS7_get_attribute(PKCS7_SIGNER_INFO *si, int nid)
795 796 797 798
	{
	return(get_attribute(si->unauth_attr,nid));
	}

U
Ulf Möller 已提交
799
static ASN1_TYPE *get_attribute(STACK *sk, int nid)
800 801 802 803 804 805 806 807 808 809 810 811
	{
	int i;
	X509_ATTRIBUTE *xa;
	ASN1_OBJECT *o;

	o=OBJ_nid2obj(nid);
	if (o == NULL) return(NULL);
	for (i=0; i<sk_num(sk); i++)
		{
		xa=(X509_ATTRIBUTE *)sk_value(sk,i);
		if (OBJ_cmp(xa->object,o) == 0)
			{
B
Ben Laurie 已提交
812 813
			if (xa->set && sk_ASN1_TYPE_num(xa->value.set))
				return(sk_ASN1_TYPE_value(xa->value.set,0));
814 815 816 817 818 819 820
			else
				return(NULL);
			}
		}
	return(NULL);
	}

U
Ulf Möller 已提交
821
ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK *sk)
822 823 824 825 826 827 828 829 830 831 832 833
	{
	X509_ATTRIBUTE *attr;
	ASN1_TYPE *astype;
	int i;
	if (!sk || !sk_num(sk)) return NULL;
	/* Search the attributes for a digest */
	for (i = 0; i < sk_num(sk); i++)
		{
		attr = (X509_ATTRIBUTE *) sk_value(sk, i);
		if (OBJ_obj2nid(attr->object) == NID_pkcs9_messageDigest)
			{
			if (!attr->set) return NULL;
B
Ben Laurie 已提交
834 835 836 837
			if (!attr->value.set
			    || !sk_ASN1_TYPE_num(attr->value.set) )
			    return NULL;
			astype = sk_ASN1_TYPE_value(attr->value.set, 0);
838 839 840 841 842 843
			return astype->value.octet_string;
			}
		}
	return NULL;
	}

U
Ulf Möller 已提交
844
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk)
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
	{
	int i;

	if (p7si->auth_attr != NULL)
		sk_pop_free(p7si->auth_attr,X509_ATTRIBUTE_free);
	p7si->auth_attr=sk_dup(sk);
	for (i=0; i<sk_num(sk); i++)
		{
		if ((sk_value(p7si->auth_attr,i)=(char *)X509_ATTRIBUTE_dup(
			(X509_ATTRIBUTE *)sk_value(sk,i))) == NULL)
			return(0);
		}
	return(1);
	}

U
Ulf Möller 已提交
860
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk)
861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
	{
	int i;

	if (p7si->unauth_attr != NULL)
		sk_pop_free(p7si->unauth_attr,X509_ATTRIBUTE_free);
	p7si->unauth_attr=sk_dup(sk);
	for (i=0; i<sk_num(sk); i++)
		{
		if ((sk_value(p7si->unauth_attr,i)=(char *)X509_ATTRIBUTE_dup(
			(X509_ATTRIBUTE *)sk_value(sk,i))) == NULL)
			return(0);
		}
	return(1);
	}

U
Ulf Möller 已提交
876
int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
877
	     void *value)
878 879 880 881
	{
	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
	}

U
Ulf Möller 已提交
882
int PKCS7_add_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
883
	     void *value)
884 885 886 887
	{
	return(add_attribute(&(p7si->unauth_attr),nid,atrtype,value));
	}

888
static int add_attribute(STACK **sk, int nid, int atrtype, void *value)
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
	{
	X509_ATTRIBUTE *attr=NULL;

	if (*sk == NULL)
		{
		*sk = sk_new(NULL);
new_attrib:
		attr=X509_ATTRIBUTE_create(nid,atrtype,value);
		sk_push(*sk,(char *)attr);
		}
	else
		{
		int i;

		for (i=0; i<sk_num(*sk); i++)
			{
			attr=(X509_ATTRIBUTE *)sk_value(*sk,i);
			if (OBJ_obj2nid(attr->object) == nid)
				{
				X509_ATTRIBUTE_free(attr);
				attr=X509_ATTRIBUTE_create(nid,atrtype,value);
				sk_value(*sk,i)=(char *)attr;
				goto end;
				}
			}
		goto new_attrib;
		}
end:
	return(1);
	}