pk7_doit.c 22.5 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
		keylen=EVP_CIPHER_key_length(evp_cipher);
		ivlen=EVP_CIPHER_iv_length(evp_cipher);

159 160 161 162 163 164 165 166
		if (ivlen > 0) {
			EVP_CIPHER_CTX *ctx;
			BIO_get_cipher_ctx(btmp, &ctx);
			if (xalg->parameter == NULL) 
						xalg->parameter=ASN1_TYPE_new();
			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
								       goto err;
		}
167 168 169 170 171 172 173
		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);
174 175 176 177 178
			if (ri->cert == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
				goto err;
				}
179 180
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_size(pkey);
181
			EVP_PKEY_free(pkey);
182 183
			if (max < jj) max=jj;
			}
184 185 186 187 188
		if ((tmp=(unsigned char *)Malloc(max)) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
189 190 191 192 193
		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);
194
			EVP_PKEY_free(pkey);
195 196 197 198 199 200
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
				Free(tmp);
				goto err;
				}
201 202
			ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
			}
203
		Free(tmp);
204 205 206 207 208 209 210

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

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
211
		btmp=NULL;
212 213 214
		}

	if (bio == NULL) /* ??????????? */
215 216 217 218 219 220
		{
		if (p7->detached)
			bio=BIO_new(BIO_s_null());
		else
			{
			bio=BIO_new(BIO_s_mem());
221 222 223 224 225
			/* 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);

226 227 228 229 230 231 232
			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)
233 234
					BIO_write(bio,(char *)os->data,
						os->length);
235 236 237 238
				}
			}
		}
	BIO_push(out,bio);
239 240 241 242 243 244 245 246 247 248
	bio=NULL;
	if (0)
		{
err:
		if (out != NULL)
			BIO_free_all(out);
		if (btmp != NULL)
			BIO_free_all(btmp);
		out=NULL;
		}
249
	return(out);
250 251 252
	}

/* int */
U
Ulf Möller 已提交
253 254
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio,
	     X509_STORE *xs)
255 256 257 258 259 260
	{
	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 已提交
261 262
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
263 264 265 266 267 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
	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)
		{
450
err:
451 452 453 454 455 456 457 458 459
		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);
460
	}
461
#endif
462

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

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

	switch (i)
		{
482 483 484 485 486 487
	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;
488 489 490 491 492
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
		os=ASN1_OCTET_STRING_new();
		p7->d.enveloped->enc_data->enc_data=os;
		break;
493
	case NID_pkcs7_signed:
494 495
		si_sk=p7->d.sign->signer_info;
		os=p7->d.sign->contents->d.data;
496 497 498 499 500
		/* If detached data then the content is excluded */
		if(p7->detached) {
			ASN1_OCTET_STRING_free(os);
			p7->d.sign->contents->d.data = NULL;
		}
501 502
		break;
		}
503

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

			j=OBJ_obj2nid(si->digest_alg->algorithm);
518 519 520 521 522 523 524

			btmp=bio;
			for (;;)
				{
				if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) 
					== NULL)
					{
525
					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST);
526 527 528 529 530
					goto err;
					}
				BIO_get_md_ctx(btmp,&mdc);
				if (mdc == NULL)
					{
531
					PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_INTERNAL_ERROR);
532 533
					goto err;
					}
534
				if (EVP_MD_type(EVP_MD_CTX_type(mdc)) == j)
535 536 537 538 539 540 541 542 543
					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)))
544 545
				{
				PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
546
				goto err;
547
				}
548 549

			sk=si->auth_attr;
550 551 552

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

				/* Add signing time */
				sign_time=X509_gmtime_adj(NULL,0);
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_signingTime,
565
					V_ASN1_UTCTIME,sign_time);
566 567 568 569 570 571 572

				/* 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,
573
					V_ASN1_OCTET_STRING,digest);
574 575 576

				/* Now sign the mess */
				EVP_SignInit(&ctx_tmp,md_tmp);
577
				x=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE,
578
					V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SET);
579
				pp=(unsigned char *)Malloc(x);
580 581
				p=pp;
				i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE,
582
					V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SET);
583 584
				EVP_SignUpdate(&ctx_tmp,pp,x);
				Free(pp);
585
				pp=NULL;
586 587
				}

588 589 590
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();

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

606
	if (!p7->detached)
607 608 609 610 611 612 613 614 615 616 617 618 619 620
		{
		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;

621 622 623 624 625 626
	ret=1;
err:
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}

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

643 644 645 646 647 648 649 650 651 652 653 654 655
	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;
		}
656
	/* XXXXXXXXXXXXXXXXXXXXXXX */
657 658
	ias=si->issuer_and_serial;

659
	x509=X509_find_by_issuer_and_serial(cert,ias->issuer,ias->serial);
660 661 662 663 664 665 666 667 668

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

701 702
	/* mdc is the digest ctx that we want, unless there are attributes,
	 * in which case the digest is the signed attributes */
703 704 705 706 707
	memcpy(&mdc_tmp,mdc,sizeof(mdc_tmp));

	sk=si->auth_attr;
	if ((sk != NULL) && (sk_num(sk) != 0))
		{
708
		unsigned char md_dat[EVP_MAX_MD_SIZE];
709
                unsigned int md_len;
710 711 712 713 714 715 716 717 718
		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;
			}
719
		if ((message_digest->length != (int)md_len) ||
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
			(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));
736 737 738 739
		/* 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.
		 */
740
		i=i2d_ASN1_SET(sk,NULL,i2d_X509_ATTRIBUTE,
741
			V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE);
742
		pp=(unsigned char *)Malloc(i);
743 744
		p=pp;
		i2d_ASN1_SET(sk,&p,i2d_X509_ATTRIBUTE,
745
			V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE);
746
		EVP_VerifyUpdate(&mdc_tmp,pp,i);
747

748
		Free(pp);
749 750 751
		}

	os=si->enc_digest;
752 753
	pkey = X509_get_pubkey(x509);
	if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
754

755 756
	i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);
	EVP_PKEY_free(pkey);
757 758 759 760 761 762 763 764 765 766 767 768
	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 已提交
769
PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx)
770 771 772 773 774 775 776 777 778 779 780 781 782 783
	{
	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 已提交
784
ASN1_TYPE *PKCS7_get_signed_attribute(PKCS7_SIGNER_INFO *si, int nid)
785 786 787 788
	{
	return(get_attribute(si->auth_attr,nid));
	}

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

U
Ulf Möller 已提交
794
static ASN1_TYPE *get_attribute(STACK *sk, int nid)
795 796 797 798 799 800 801 802 803 804 805 806
	{
	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 已提交
807 808
			if (xa->set && sk_ASN1_TYPE_num(xa->value.set))
				return(sk_ASN1_TYPE_value(xa->value.set,0));
809 810 811 812 813 814 815
			else
				return(NULL);
			}
		}
	return(NULL);
	}

U
Ulf Möller 已提交
816
ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK *sk)
817 818 819 820 821 822 823 824 825 826 827 828
	{
	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 已提交
829 830 831 832
			if (!attr->value.set
			    || !sk_ASN1_TYPE_num(attr->value.set) )
			    return NULL;
			astype = sk_ASN1_TYPE_value(attr->value.set, 0);
833 834 835 836 837 838
			return astype->value.octet_string;
			}
		}
	return NULL;
	}

U
Ulf Möller 已提交
839
int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk)
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
	{
	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 已提交
855
int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk)
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870
	{
	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 已提交
871
int PKCS7_add_signed_attribute(PKCS7_SIGNER_INFO *p7si, int nid, int atrtype,
872
	     void *value)
873 874 875 876
	{
	return(add_attribute(&(p7si->auth_attr),nid,atrtype,value));
	}

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

883
static int add_attribute(STACK **sk, int nid, int atrtype, void *value)
884 885 886 887 888 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
	{
	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);
	}