os/ossrv/ssl/libcrypto/src/crypto/pkcs7/pk7_smime.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* pk7_smime.c */
sl@0
     2
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
sl@0
     3
 * project.
sl@0
     4
 */
sl@0
     5
/* ====================================================================
sl@0
     6
 * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
sl@0
     7
 *
sl@0
     8
 * Redistribution and use in source and binary forms, with or without
sl@0
     9
 * modification, are permitted provided that the following conditions
sl@0
    10
 * are met:
sl@0
    11
 *
sl@0
    12
 * 1. Redistributions of source code must retain the above copyright
sl@0
    13
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    14
 *
sl@0
    15
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    16
 *    notice, this list of conditions and the following disclaimer in
sl@0
    17
 *    the documentation and/or other materials provided with the
sl@0
    18
 *    distribution.
sl@0
    19
 *
sl@0
    20
 * 3. All advertising materials mentioning features or use of this
sl@0
    21
 *    software must display the following acknowledgment:
sl@0
    22
 *    "This product includes software developed by the OpenSSL Project
sl@0
    23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
sl@0
    24
 *
sl@0
    25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    26
 *    endorse or promote products derived from this software without
sl@0
    27
 *    prior written permission. For written permission, please contact
sl@0
    28
 *    licensing@OpenSSL.org.
sl@0
    29
 *
sl@0
    30
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    31
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    32
 *    permission of the OpenSSL Project.
sl@0
    33
 *
sl@0
    34
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    35
 *    acknowledgment:
sl@0
    36
 *    "This product includes software developed by the OpenSSL Project
sl@0
    37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
sl@0
    38
 *
sl@0
    39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    51
 * ====================================================================
sl@0
    52
 *
sl@0
    53
 * This product includes cryptographic software written by Eric Young
sl@0
    54
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
    55
 * Hudson (tjh@cryptsoft.com).
sl@0
    56
 *
sl@0
    57
 */
sl@0
    58
/*
sl@0
    59
 © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
sl@0
    60
 */
sl@0
    61
/* Simple PKCS#7 processing functions */
sl@0
    62
sl@0
    63
#include <stdio.h>
sl@0
    64
#include "cryptlib.h"
sl@0
    65
#include <openssl/x509.h>
sl@0
    66
#include <openssl/x509v3.h>
sl@0
    67
sl@0
    68
EXPORT_C PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
sl@0
    69
		  BIO *data, int flags)
sl@0
    70
{
sl@0
    71
	PKCS7 *p7 = NULL;
sl@0
    72
	PKCS7_SIGNER_INFO *si;
sl@0
    73
	BIO *p7bio = NULL;
sl@0
    74
	STACK_OF(X509_ALGOR) *smcap = NULL;
sl@0
    75
	int i;
sl@0
    76
sl@0
    77
	if(!X509_check_private_key(signcert, pkey)) {
sl@0
    78
		PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
sl@0
    79
                return NULL;
sl@0
    80
	}
sl@0
    81
sl@0
    82
	if(!(p7 = PKCS7_new())) {
sl@0
    83
		PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
sl@0
    84
		return NULL;
sl@0
    85
	}
sl@0
    86
sl@0
    87
	if (!PKCS7_set_type(p7, NID_pkcs7_signed))
sl@0
    88
		goto err;
sl@0
    89
sl@0
    90
	if (!PKCS7_content_new(p7, NID_pkcs7_data))
sl@0
    91
		goto err;
sl@0
    92
sl@0
    93
	if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) {
sl@0
    94
		PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
sl@0
    95
		goto err;
sl@0
    96
	}
sl@0
    97
sl@0
    98
	if(!(flags & PKCS7_NOCERTS)) {
sl@0
    99
		if (!PKCS7_add_certificate(p7, signcert))
sl@0
   100
			goto err;
sl@0
   101
		if(certs) for(i = 0; i < sk_X509_num(certs); i++)
sl@0
   102
			if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i)))
sl@0
   103
				goto err;
sl@0
   104
	}
sl@0
   105
sl@0
   106
	if(!(flags & PKCS7_NOATTR)) {
sl@0
   107
		if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
sl@0
   108
				V_ASN1_OBJECT, OBJ_nid2obj(NID_pkcs7_data)))
sl@0
   109
			goto err;
sl@0
   110
		/* Add SMIMECapabilities */
sl@0
   111
		if(!(flags & PKCS7_NOSMIMECAP))
sl@0
   112
		{
sl@0
   113
		if(!(smcap = sk_X509_ALGOR_new_null())) {
sl@0
   114
			PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
sl@0
   115
			goto err;
sl@0
   116
		}
sl@0
   117
#ifndef OPENSSL_NO_DES
sl@0
   118
		if (!PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1))
sl@0
   119
			goto err;
sl@0
   120
#endif
sl@0
   121
#ifndef OPENSSL_NO_RC2
sl@0
   122
		if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128))
sl@0
   123
			goto err;
sl@0
   124
		if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64))
sl@0
   125
			goto err;
sl@0
   126
#endif
sl@0
   127
#ifndef OPENSSL_NO_DES
sl@0
   128
		if (!PKCS7_simple_smimecap (smcap, NID_des_cbc, -1))
sl@0
   129
			goto err;
sl@0
   130
#endif
sl@0
   131
#ifndef OPENSSL_NO_RC2
sl@0
   132
		if (!PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40))
sl@0
   133
			goto err;
sl@0
   134
#endif
sl@0
   135
		if (!PKCS7_add_attrib_smimecap (si, smcap))
sl@0
   136
			goto err;
sl@0
   137
		sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
sl@0
   138
		smcap = NULL;
sl@0
   139
		}
sl@0
   140
	}
sl@0
   141
	if(flags & PKCS7_DETACHED)PKCS7_set_detached(p7, 1);
sl@0
   142
sl@0
   143
	if (flags & PKCS7_STREAM)
sl@0
   144
		return p7;
sl@0
   145
sl@0
   146
	if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
sl@0
   147
		PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
sl@0
   148
		goto err;
sl@0
   149
	}
sl@0
   150
sl@0
   151
	SMIME_crlf_copy(data, p7bio, flags);
sl@0
   152
sl@0
   153
	        if (!PKCS7_dataFinal(p7,p7bio)) {
sl@0
   154
		PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN);
sl@0
   155
		goto err;
sl@0
   156
	}
sl@0
   157
sl@0
   158
	BIO_free_all(p7bio);
sl@0
   159
	return p7;
sl@0
   160
err:
sl@0
   161
	sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
sl@0
   162
	BIO_free_all(p7bio);
sl@0
   163
	PKCS7_free(p7);
sl@0
   164
	return NULL;
sl@0
   165
}
sl@0
   166
sl@0
   167
EXPORT_C int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
sl@0
   168
					BIO *indata, BIO *out, int flags)
sl@0
   169
{
sl@0
   170
	STACK_OF(X509) *signers;
sl@0
   171
	X509 *signer;
sl@0
   172
	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
sl@0
   173
	PKCS7_SIGNER_INFO *si;
sl@0
   174
	X509_STORE_CTX cert_ctx;
sl@0
   175
#ifndef SYMBIAN	
sl@0
   176
	char buf[4096];
sl@0
   177
#else
sl@0
   178
  char buf[512];
sl@0
   179
#endif
sl@0
   180
	
sl@0
   181
	int i, j=0, k, ret = 0;
sl@0
   182
	BIO *p7bio;
sl@0
   183
	BIO *tmpin, *tmpout;
sl@0
   184
sl@0
   185
	if(!p7) {
sl@0
   186
		PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
sl@0
   187
		return 0;
sl@0
   188
	}
sl@0
   189
sl@0
   190
	if(!PKCS7_type_is_signed(p7)) {
sl@0
   191
		PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
sl@0
   192
		return 0;
sl@0
   193
	}
sl@0
   194
sl@0
   195
	/* Check for no data and no content: no data to verify signature */
sl@0
   196
	if(PKCS7_get_detached(p7) && !indata) {
sl@0
   197
		PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
sl@0
   198
		return 0;
sl@0
   199
	}
sl@0
   200
#if 0
sl@0
   201
	/* NB: this test commented out because some versions of Netscape
sl@0
   202
	 * illegally include zero length content when signing data.
sl@0
   203
	 */
sl@0
   204
sl@0
   205
	/* Check for data and content: two sets of data */
sl@0
   206
	if(!PKCS7_get_detached(p7) && indata) {
sl@0
   207
				PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CONTENT_AND_DATA_PRESENT);
sl@0
   208
		return 0;
sl@0
   209
	}
sl@0
   210
#endif
sl@0
   211
sl@0
   212
	sinfos = PKCS7_get_signer_info(p7);
sl@0
   213
sl@0
   214
	if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
sl@0
   215
		PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
sl@0
   216
		return 0;
sl@0
   217
	}
sl@0
   218
sl@0
   219
sl@0
   220
	signers = PKCS7_get0_signers(p7, certs, flags);
sl@0
   221
sl@0
   222
	if(!signers) return 0;
sl@0
   223
sl@0
   224
	/* Now verify the certificates */
sl@0
   225
sl@0
   226
	if (!(flags & PKCS7_NOVERIFY)) for (k = 0; k < sk_X509_num(signers); k++) {
sl@0
   227
		signer = sk_X509_value (signers, k);
sl@0
   228
		if (!(flags & PKCS7_NOCHAIN)) {
sl@0
   229
			if(!X509_STORE_CTX_init(&cert_ctx, store, signer,
sl@0
   230
							p7->d.sign->cert))
sl@0
   231
				{
sl@0
   232
				PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB);
sl@0
   233
				sk_X509_free(signers);
sl@0
   234
				return 0;
sl@0
   235
				}
sl@0
   236
			X509_STORE_CTX_set_purpose(&cert_ctx,
sl@0
   237
						X509_PURPOSE_SMIME_SIGN);
sl@0
   238
		} else if(!X509_STORE_CTX_init (&cert_ctx, store, signer, NULL)) {
sl@0
   239
			PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_X509_LIB);
sl@0
   240
			sk_X509_free(signers);
sl@0
   241
			return 0;
sl@0
   242
		}
sl@0
   243
		if (!(flags & PKCS7_NOCRL))
sl@0
   244
			X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl);
sl@0
   245
		i = X509_verify_cert(&cert_ctx);
sl@0
   246
		if (i <= 0) j = X509_STORE_CTX_get_error(&cert_ctx);
sl@0
   247
		X509_STORE_CTX_cleanup(&cert_ctx);
sl@0
   248
		if (i <= 0) {
sl@0
   249
			PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_CERTIFICATE_VERIFY_ERROR);
sl@0
   250
			ERR_add_error_data(2, "Verify error:",
sl@0
   251
					 X509_verify_cert_error_string(j));
sl@0
   252
			sk_X509_free(signers);
sl@0
   253
			return 0;
sl@0
   254
		}
sl@0
   255
		/* Check for revocation status here */
sl@0
   256
	}
sl@0
   257
sl@0
   258
	/* Performance optimization: if the content is a memory BIO then
sl@0
   259
	 * store its contents in a temporary read only memory BIO. This
sl@0
   260
	 * avoids potentially large numbers of slow copies of data which will
sl@0
   261
	 * occur when reading from a read write memory BIO when signatures
sl@0
   262
	 * are calculated.
sl@0
   263
	 */
sl@0
   264
sl@0
   265
	if (indata && (BIO_method_type(indata) == BIO_TYPE_MEM))
sl@0
   266
		{
sl@0
   267
		char *ptr;
sl@0
   268
		long len;
sl@0
   269
		len = BIO_get_mem_data(indata, &ptr);
sl@0
   270
		tmpin = BIO_new_mem_buf(ptr, len);
sl@0
   271
		if (tmpin == NULL)
sl@0
   272
			{
sl@0
   273
			PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
sl@0
   274
			return 0;
sl@0
   275
			}
sl@0
   276
		}
sl@0
   277
	else
sl@0
   278
		tmpin = indata;
sl@0
   279
		
sl@0
   280
sl@0
   281
	if (!(p7bio=PKCS7_dataInit(p7,tmpin)))
sl@0
   282
		goto err;
sl@0
   283
sl@0
   284
	if(flags & PKCS7_TEXT) {
sl@0
   285
		if(!(tmpout = BIO_new(BIO_s_mem()))) {
sl@0
   286
			PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
sl@0
   287
			goto err;
sl@0
   288
		}
sl@0
   289
	} else tmpout = out;
sl@0
   290
sl@0
   291
	/* We now have to 'read' from p7bio to calculate digests etc. */
sl@0
   292
	for (;;)
sl@0
   293
	{
sl@0
   294
		i=BIO_read(p7bio,buf,sizeof(buf));
sl@0
   295
		if (i <= 0) break;
sl@0
   296
		if (tmpout) BIO_write(tmpout, buf, i);
sl@0
   297
	}
sl@0
   298
sl@0
   299
	if(flags & PKCS7_TEXT) {
sl@0
   300
		if(!SMIME_text(tmpout, out)) {
sl@0
   301
			PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SMIME_TEXT_ERROR);
sl@0
   302
			BIO_free(tmpout);
sl@0
   303
			goto err;
sl@0
   304
		}
sl@0
   305
		BIO_free(tmpout);
sl@0
   306
	}
sl@0
   307
sl@0
   308
	/* Now Verify All Signatures */
sl@0
   309
	if (!(flags & PKCS7_NOSIGS))
sl@0
   310
	    for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
sl@0
   311
		{
sl@0
   312
		si=sk_PKCS7_SIGNER_INFO_value(sinfos,i);
sl@0
   313
		signer = sk_X509_value (signers, i);
sl@0
   314
		j=PKCS7_signatureVerify(p7bio,p7,si, signer);
sl@0
   315
		if (j <= 0) {
sl@0
   316
			PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SIGNATURE_FAILURE);
sl@0
   317
			goto err;
sl@0
   318
		}
sl@0
   319
	}
sl@0
   320
sl@0
   321
	ret = 1;
sl@0
   322
sl@0
   323
	err:
sl@0
   324
	
sl@0
   325
	if (tmpin == indata)
sl@0
   326
		{
sl@0
   327
		if (indata) BIO_pop(p7bio);
sl@0
   328
		}
sl@0
   329
	BIO_free_all(p7bio);
sl@0
   330
sl@0
   331
	sk_X509_free(signers);
sl@0
   332
sl@0
   333
	return ret;
sl@0
   334
}
sl@0
   335
sl@0
   336
EXPORT_C STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
sl@0
   337
{
sl@0
   338
	STACK_OF(X509) *signers;
sl@0
   339
	STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
sl@0
   340
	PKCS7_SIGNER_INFO *si;
sl@0
   341
	PKCS7_ISSUER_AND_SERIAL *ias;
sl@0
   342
	X509 *signer;
sl@0
   343
	int i;
sl@0
   344
sl@0
   345
	if(!p7) {
sl@0
   346
		PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_INVALID_NULL_POINTER);
sl@0
   347
		return NULL;
sl@0
   348
	}
sl@0
   349
sl@0
   350
	if(!PKCS7_type_is_signed(p7)) {
sl@0
   351
		PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
sl@0
   352
		return NULL;
sl@0
   353
	}
sl@0
   354
sl@0
   355
	/* Collect all the signers together */
sl@0
   356
sl@0
   357
	sinfos = PKCS7_get_signer_info(p7);
sl@0
   358
sl@0
   359
	if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
sl@0
   360
		PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_NO_SIGNERS);
sl@0
   361
		return NULL;
sl@0
   362
	}
sl@0
   363
sl@0
   364
	if(!(signers = sk_X509_new_null())) {
sl@0
   365
		PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,ERR_R_MALLOC_FAILURE);
sl@0
   366
		return NULL;
sl@0
   367
	}
sl@0
   368
sl@0
   369
	for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
sl@0
   370
	{
sl@0
   371
	    si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
sl@0
   372
	    ias = si->issuer_and_serial;
sl@0
   373
	    signer = NULL;
sl@0
   374
		/* If any certificates passed they take priority */
sl@0
   375
	    if (certs) signer = X509_find_by_issuer_and_serial (certs,
sl@0
   376
					 	ias->issuer, ias->serial);
sl@0
   377
	    if (!signer && !(flags & PKCS7_NOINTERN)
sl@0
   378
			&& p7->d.sign->cert) signer =
sl@0
   379
		              X509_find_by_issuer_and_serial (p7->d.sign->cert,
sl@0
   380
					      	ias->issuer, ias->serial);
sl@0
   381
	    if (!signer) {
sl@0
   382
			PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
sl@0
   383
			sk_X509_free(signers);
sl@0
   384
			return NULL;
sl@0
   385
	    }
sl@0
   386
sl@0
   387
	    if (!sk_X509_push(signers, signer)) {
sl@0
   388
			sk_X509_free(signers);
sl@0
   389
			return NULL;
sl@0
   390
	    }
sl@0
   391
	}
sl@0
   392
	return signers;
sl@0
   393
}
sl@0
   394
sl@0
   395
sl@0
   396
/* Build a complete PKCS#7 enveloped data */
sl@0
   397
sl@0
   398
EXPORT_C PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
sl@0
   399
								int flags)
sl@0
   400
{
sl@0
   401
	PKCS7 *p7;
sl@0
   402
	BIO *p7bio = NULL;
sl@0
   403
	int i;
sl@0
   404
	X509 *x509;
sl@0
   405
	if(!(p7 = PKCS7_new())) {
sl@0
   406
		PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
sl@0
   407
		return NULL;
sl@0
   408
	}
sl@0
   409
sl@0
   410
	if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
sl@0
   411
		goto err;
sl@0
   412
	if(!PKCS7_set_cipher(p7, cipher)) {
sl@0
   413
		PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_ERROR_SETTING_CIPHER);
sl@0
   414
		goto err;
sl@0
   415
	}
sl@0
   416
sl@0
   417
	for(i = 0; i < sk_X509_num(certs); i++) {
sl@0
   418
		x509 = sk_X509_value(certs, i);
sl@0
   419
		if(!PKCS7_add_recipient(p7, x509)) {
sl@0
   420
			PKCS7err(PKCS7_F_PKCS7_ENCRYPT,
sl@0
   421
					PKCS7_R_ERROR_ADDING_RECIPIENT);
sl@0
   422
			goto err;
sl@0
   423
		}
sl@0
   424
	}
sl@0
   425
sl@0
   426
	if(!(p7bio = PKCS7_dataInit(p7, NULL))) {
sl@0
   427
		PKCS7err(PKCS7_F_PKCS7_ENCRYPT,ERR_R_MALLOC_FAILURE);
sl@0
   428
		goto err;
sl@0
   429
	}
sl@0
   430
sl@0
   431
	SMIME_crlf_copy(in, p7bio, flags);
sl@0
   432
sl@0
   433
	(void)BIO_flush(p7bio);
sl@0
   434
sl@0
   435
        if (!PKCS7_dataFinal(p7,p7bio)) {
sl@0
   436
		PKCS7err(PKCS7_F_PKCS7_ENCRYPT,PKCS7_R_PKCS7_DATAFINAL_ERROR);
sl@0
   437
		goto err;
sl@0
   438
	}
sl@0
   439
        BIO_free_all(p7bio);
sl@0
   440
sl@0
   441
	return p7;
sl@0
   442
sl@0
   443
	err:
sl@0
   444
sl@0
   445
	BIO_free_all(p7bio);
sl@0
   446
	PKCS7_free(p7);
sl@0
   447
	return NULL;
sl@0
   448
sl@0
   449
}
sl@0
   450
sl@0
   451
EXPORT_C int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
sl@0
   452
{
sl@0
   453
	BIO *tmpmem;
sl@0
   454
	int ret, i;
sl@0
   455
#ifndef SYMBIAN	
sl@0
   456
	char buf[4096];
sl@0
   457
#else
sl@0
   458
  char buf[512];
sl@0
   459
#endif	
sl@0
   460
sl@0
   461
	if(!p7) {
sl@0
   462
		PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER);
sl@0
   463
		return 0;
sl@0
   464
	}
sl@0
   465
sl@0
   466
	if(!PKCS7_type_is_enveloped(p7)) {
sl@0
   467
		PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE);
sl@0
   468
		return 0;
sl@0
   469
	}
sl@0
   470
sl@0
   471
	if(cert && !X509_check_private_key(cert, pkey)) {
sl@0
   472
		PKCS7err(PKCS7_F_PKCS7_DECRYPT,
sl@0
   473
				PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
sl@0
   474
		return 0;
sl@0
   475
	}
sl@0
   476
sl@0
   477
	if(!(tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert))) {
sl@0
   478
		PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR);
sl@0
   479
		return 0;
sl@0
   480
	}
sl@0
   481
sl@0
   482
	if (flags & PKCS7_TEXT) {
sl@0
   483
		BIO *tmpbuf, *bread;
sl@0
   484
		/* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
sl@0
   485
		if(!(tmpbuf = BIO_new(BIO_f_buffer()))) {
sl@0
   486
			PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
sl@0
   487
			BIO_free_all(tmpmem);
sl@0
   488
			return 0;
sl@0
   489
		}
sl@0
   490
		if(!(bread = BIO_push(tmpbuf, tmpmem))) {
sl@0
   491
			PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
sl@0
   492
			BIO_free_all(tmpbuf);
sl@0
   493
			BIO_free_all(tmpmem);
sl@0
   494
			return 0;
sl@0
   495
		}
sl@0
   496
		ret = SMIME_text(bread, data);
sl@0
   497
		BIO_free_all(bread);
sl@0
   498
		return ret;
sl@0
   499
	} else {
sl@0
   500
		for(;;) {
sl@0
   501
			i = BIO_read(tmpmem, buf, sizeof(buf));
sl@0
   502
			if(i <= 0) break;
sl@0
   503
			BIO_write(data, buf, i);
sl@0
   504
		}
sl@0
   505
		BIO_free_all(tmpmem);
sl@0
   506
		return 1;
sl@0
   507
	}
sl@0
   508
}