Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/crypto/pkcs7/pk7_smime.c
Line
Count
Source
1
/*
2
 * Copyright 1999-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
/* Simple PKCS#7 processing functions */
11
12
#include <stdio.h>
13
#include "internal/cryptlib.h"
14
#include "crypto/x509.h"
15
#include <openssl/x509.h>
16
#include <openssl/x509v3.h>
17
#include "pk7_local.h"
18
19
14.2k
#define BUFFERSIZE 4096
20
21
static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
22
23
PKCS7 *PKCS7_sign_ex(X509 *signcert, EVP_PKEY *pkey, const STACK_OF(X509) *certs,
24
    BIO *data, int flags, OSSL_LIB_CTX *libctx, const char *propq)
25
0
{
26
0
    PKCS7 *p7;
27
0
    int i;
28
29
0
    if ((p7 = PKCS7_new_ex(libctx, propq)) == NULL) {
30
0
        ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB);
31
0
        return NULL;
32
0
    }
33
34
0
    if (!PKCS7_set_type(p7, NID_pkcs7_signed))
35
0
        goto err;
36
37
0
    if (!PKCS7_content_new(p7, NID_pkcs7_data))
38
0
        goto err;
39
40
0
    if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) {
41
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNER_ERROR);
42
0
        goto err;
43
0
    }
44
45
0
    if (!(flags & PKCS7_NOCERTS)) {
46
0
        for (i = 0; i < sk_X509_num(certs); i++) {
47
0
            if (!PKCS7_add_certificate(p7, sk_X509_value(certs, i)))
48
0
                goto err;
49
0
        }
50
0
    }
51
52
0
    if (flags & PKCS7_DETACHED)
53
0
        PKCS7_set_detached(p7, 1);
54
55
0
    if (flags & (PKCS7_STREAM | PKCS7_PARTIAL))
56
0
        return p7;
57
58
0
    if (PKCS7_final(p7, data, flags))
59
0
        return p7;
60
61
0
err:
62
0
    PKCS7_free(p7);
63
0
    return NULL;
64
0
}
65
66
PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, const STACK_OF(X509) *certs,
67
    BIO *data, int flags)
68
0
{
69
0
    return PKCS7_sign_ex(signcert, pkey, certs, data, flags, NULL, NULL);
70
0
}
71
72
int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
73
0
{
74
0
    BIO *p7bio;
75
0
    int ret = 0;
76
77
0
    if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
78
0
        ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB);
79
0
        return 0;
80
0
    }
81
82
0
    if (!SMIME_crlf_copy(data, p7bio, flags))
83
0
        goto err;
84
85
0
    (void)BIO_flush(p7bio);
86
87
0
    if (!PKCS7_dataFinal(p7, p7bio)) {
88
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_PKCS7_DATASIGN);
89
0
        goto err;
90
0
    }
91
0
    ret = 1;
92
0
err:
93
0
    BIO_free_all(p7bio);
94
95
0
    return ret;
96
0
}
97
98
/* Check to see if a cipher exists and if so add S/MIME capabilities */
99
100
static int add_cipher_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg,
101
    OSSL_LIB_CTX *libctx, const char *propq)
102
0
{
103
0
    EVP_CIPHER *cipher;
104
105
0
    ERR_set_mark();
106
0
    cipher = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(nid), propq);
107
0
    ERR_pop_to_mark();
108
0
    if (cipher != NULL) {
109
0
        EVP_CIPHER_free(cipher);
110
0
        return PKCS7_simple_smimecap(sk, nid, arg);
111
0
    }
112
0
    return 1;
113
0
}
114
115
static int add_digest_smcap(STACK_OF(X509_ALGOR) *sk, int nid, int arg,
116
    OSSL_LIB_CTX *libctx, const char *propq)
117
0
{
118
0
    EVP_MD *md;
119
120
0
    ERR_set_mark();
121
0
    md = EVP_MD_fetch(libctx, OBJ_nid2sn(nid), propq);
122
0
    ERR_pop_to_mark();
123
0
    if (md != NULL) {
124
0
        EVP_MD_free(md);
125
0
        return PKCS7_simple_smimecap(sk, nid, arg);
126
0
    }
127
0
    return 1;
128
0
}
129
130
PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
131
    EVP_PKEY *pkey, const EVP_MD *md,
132
    int flags)
133
0
{
134
0
    PKCS7_SIGNER_INFO *si = NULL;
135
0
    STACK_OF(X509_ALGOR) *smcap = NULL;
136
0
    OSSL_LIB_CTX *libctx;
137
0
    const char *propq;
138
139
0
    if (!X509_check_private_key(signcert, pkey)) {
140
0
        ERR_raise(ERR_LIB_PKCS7,
141
0
            PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
142
0
        return NULL;
143
0
    }
144
145
0
    if ((si = PKCS7_add_signature(p7, signcert, pkey, md)) == NULL) {
146
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
147
0
        return NULL;
148
0
    }
149
150
0
    si->ctx = ossl_pkcs7_get0_ctx(p7);
151
0
    if (!(flags & PKCS7_NOCERTS)) {
152
0
        if (!PKCS7_add_certificate(p7, signcert))
153
0
            goto err;
154
0
    }
155
156
0
    if (!(flags & PKCS7_NOATTR)) {
157
0
        if (!PKCS7_add_attrib_content_type(si, NULL))
158
0
            goto err;
159
        /* Add SMIMECapabilities */
160
0
        if (!(flags & PKCS7_NOSMIMECAP)) {
161
0
            if ((smcap = sk_X509_ALGOR_new_null()) == NULL) {
162
0
                ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB);
163
0
                goto err;
164
0
            }
165
0
            libctx = ossl_pkcs7_ctx_get0_libctx(si->ctx);
166
0
            propq = ossl_pkcs7_ctx_get0_propq(si->ctx);
167
0
            if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1, libctx, propq)
168
0
                || !add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1, libctx, propq)
169
0
                || !add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1, libctx, propq)
170
0
                || !add_digest_smcap(smcap, NID_id_GostR3411_94, -1, libctx, propq)
171
0
                || !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1, libctx, propq)
172
0
                || !add_cipher_smcap(smcap, NID_aes_192_cbc, -1, libctx, propq)
173
0
                || !add_cipher_smcap(smcap, NID_aes_128_cbc, -1, libctx, propq)
174
0
                || !add_cipher_smcap(smcap, NID_des_ede3_cbc, -1, libctx, propq)
175
0
                || !add_cipher_smcap(smcap, NID_rc2_cbc, 128, libctx, propq)
176
0
                || !PKCS7_add_attrib_smimecap(si, smcap))
177
0
                goto err;
178
0
            sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
179
0
            smcap = NULL;
180
0
        }
181
0
        if (flags & PKCS7_REUSE_DIGEST) {
182
0
            if (!pkcs7_copy_existing_digest(p7, si))
183
0
                goto err;
184
0
            if (!(flags & PKCS7_PARTIAL)
185
0
                && !PKCS7_SIGNER_INFO_sign(si))
186
0
                goto err;
187
0
        }
188
0
    }
189
0
    return si;
190
0
err:
191
0
    sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
192
0
    return NULL;
193
0
}
194
195
/*
196
 * Search for a digest matching SignerInfo digest type and if found copy
197
 * across.
198
 */
199
200
static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si)
201
0
{
202
0
    int i;
203
0
    STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
204
0
    PKCS7_SIGNER_INFO *sitmp;
205
0
    const ASN1_OCTET_STRING *osdig = NULL;
206
0
    sinfos = PKCS7_get_signer_info(p7);
207
0
    for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
208
0
        sitmp = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
209
0
        if (si == sitmp)
210
0
            break;
211
0
        if (sk_X509_ATTRIBUTE_num(sitmp->auth_attr) <= 0)
212
0
            continue;
213
0
        if (!OBJ_cmp(si->digest_alg->algorithm, sitmp->digest_alg->algorithm)) {
214
0
            osdig = PKCS7_digest_from_attributes(sitmp->auth_attr);
215
0
            break;
216
0
        }
217
0
    }
218
219
0
    if (osdig != NULL) {
220
0
        size_t len;
221
0
        len = ASN1_STRING_get_length(osdig);
222
0
        if (len > INT_MAX)
223
0
            goto err;
224
0
        return PKCS7_add1_attrib_digest(si, ASN1_STRING_get0_data(osdig), (int)len);
225
0
    }
226
227
0
err:
228
0
    ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_MATCHING_DIGEST_TYPE_FOUND);
229
0
    return 0;
230
0
}
231
232
/* This strongly overlaps with CMS_verify(), partly with PKCS7_dataVerify() */
233
int PKCS7_verify(PKCS7 *p7, const STACK_OF(X509) *certs, X509_STORE *store,
234
    BIO *indata, BIO *out, int flags)
235
2.55k
{
236
2.55k
    STACK_OF(X509) *signers;
237
2.55k
    STACK_OF(X509) *included_certs;
238
2.55k
    STACK_OF(X509) *untrusted = NULL;
239
2.55k
    X509 *signer;
240
2.55k
    STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
241
2.55k
    PKCS7_SIGNER_INFO *si;
242
2.55k
    X509_STORE_CTX *cert_ctx = NULL;
243
2.55k
    char *buf = NULL;
244
2.55k
    int i, j = 0, k, ret = 0;
245
2.55k
    BIO *p7bio = NULL;
246
2.55k
    BIO *tmpout = NULL;
247
2.55k
    BIO *next = NULL;
248
2.55k
    const PKCS7_CTX *p7_ctx;
249
250
2.55k
    if (p7 == NULL) {
251
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
252
0
        return 0;
253
0
    }
254
255
2.55k
    if (!PKCS7_type_is_signed(p7)) {
256
78
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
257
78
        return 0;
258
78
    }
259
260
    /* Check for no data and no content: no data to verify signature */
261
2.47k
    if (PKCS7_get_detached(p7) && indata == NULL) {
262
19
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
263
19
        return 0;
264
19
    }
265
266
2.45k
    if (flags & PKCS7_NO_DUAL_CONTENT) {
267
        /*
268
         * This was originally "#if 0" because we thought that only old broken
269
         * Netscape did this.  It turns out that Authenticode uses this kind
270
         * of "extended" PKCS7 format, and things like UEFI secure boot and
271
         * tools like osslsigncode need it.  In Authenticode the verification
272
         * process is different, but the existing PKCs7 verification works.
273
         */
274
0
        if (!PKCS7_get_detached(p7) && indata != NULL) {
275
0
            ERR_raise(ERR_LIB_PKCS7, PKCS7_R_CONTENT_AND_DATA_PRESENT);
276
0
            return 0;
277
0
        }
278
0
    }
279
280
2.45k
    sinfos = PKCS7_get_signer_info(p7);
281
282
2.45k
    if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
283
6
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_SIGNATURES_ON_DATA);
284
6
        return 0;
285
6
    }
286
287
2.44k
    signers = PKCS7_get0_signers(p7, certs, flags);
288
2.44k
    if (signers == NULL)
289
80
        return 0;
290
291
    /* Now verify the certificates */
292
2.36k
    p7_ctx = ossl_pkcs7_get0_ctx(p7);
293
2.36k
    cert_ctx = X509_STORE_CTX_new_ex(ossl_pkcs7_ctx_get0_libctx(p7_ctx),
294
2.36k
        ossl_pkcs7_ctx_get0_propq(p7_ctx));
295
2.36k
    if (cert_ctx == NULL)
296
0
        goto err;
297
2.36k
    if ((flags & PKCS7_NOVERIFY) == 0) {
298
0
        if (!ossl_x509_add_certs_new(&untrusted, certs, X509_ADD_FLAG_NO_DUP))
299
0
            goto err;
300
0
        included_certs = pkcs7_get0_certificates(p7);
301
0
        if ((flags & PKCS7_NOCHAIN) == 0
302
0
            && !ossl_x509_add_certs_new(&untrusted, included_certs,
303
0
                X509_ADD_FLAG_NO_DUP))
304
0
            goto err;
305
306
0
        for (k = 0; k < sk_X509_num(signers); k++) {
307
0
            signer = sk_X509_value(signers, k);
308
0
            if (!X509_STORE_CTX_init(cert_ctx, store, signer, untrusted)) {
309
0
                ERR_raise(ERR_LIB_PKCS7, ERR_R_X509_LIB);
310
0
                goto err;
311
0
            }
312
0
            if ((flags & PKCS7_NOCHAIN) == 0
313
0
                && !X509_STORE_CTX_set_default(cert_ctx, "smime_sign"))
314
0
                goto err;
315
0
            if (!(flags & PKCS7_NOCRL))
316
0
                X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl);
317
0
            i = X509_verify_cert(cert_ctx);
318
0
            if (i <= 0) {
319
0
                j = X509_STORE_CTX_get_error(cert_ctx);
320
0
                ERR_raise_data(ERR_LIB_PKCS7, PKCS7_R_CERTIFICATE_VERIFY_ERROR,
321
0
                    "Verify error: %s",
322
0
                    X509_verify_cert_error_string(j));
323
0
                goto err;
324
0
            }
325
            /* Check for revocation status here */
326
0
        }
327
0
    }
328
329
2.36k
    if ((p7bio = PKCS7_dataInit(p7, indata)) == NULL)
330
45
        goto err;
331
332
2.32k
    if (flags & PKCS7_TEXT) {
333
0
        if ((tmpout = BIO_new(BIO_s_mem())) == NULL) {
334
0
            ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
335
0
            goto err;
336
0
        }
337
0
        BIO_set_mem_eof_return(tmpout, 0);
338
0
    } else
339
2.32k
        tmpout = out;
340
341
    /* We now have to 'read' from p7bio to calculate digests etc. */
342
2.32k
    if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL)
343
0
        goto err;
344
14.2k
    for (;;) {
345
14.2k
        i = BIO_read(p7bio, buf, BUFFERSIZE);
346
14.2k
        if (i <= 0)
347
2.32k
            break;
348
11.9k
        if (tmpout)
349
11.9k
            BIO_write(tmpout, buf, i);
350
11.9k
    }
351
352
2.32k
    if (flags & PKCS7_TEXT) {
353
0
        if (!SMIME_text(tmpout, out)) {
354
0
            ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SMIME_TEXT_ERROR);
355
0
            goto err;
356
0
        }
357
0
    }
358
359
    /* Now Verify All Signatures */
360
2.32k
    if (!(flags & PKCS7_NOSIGS))
361
2.44k
        for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
362
2.38k
            si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
363
2.38k
            signer = sk_X509_value(signers, i);
364
2.38k
            j = PKCS7_signatureVerify(p7bio, p7, si, signer);
365
2.38k
            if (j <= 0) {
366
2.26k
                ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNATURE_FAILURE);
367
2.26k
                goto err;
368
2.26k
            }
369
2.38k
        }
370
371
60
    ret = 1;
372
373
2.36k
err:
374
2.36k
    if (flags & PKCS7_TEXT)
375
0
        BIO_free(tmpout);
376
2.36k
    X509_STORE_CTX_free(cert_ctx);
377
2.36k
    OPENSSL_free(buf);
378
4.88k
    while (p7bio != NULL && p7bio != indata) {
379
2.51k
        next = BIO_pop(p7bio);
380
2.51k
        BIO_free(p7bio);
381
2.51k
        p7bio = next;
382
2.51k
    }
383
2.36k
    sk_X509_free(signers);
384
2.36k
    sk_X509_free(untrusted);
385
2.36k
    return ret;
386
60
}
387
388
STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, const STACK_OF(X509) *certs, int flags)
389
2.44k
{
390
2.44k
    STACK_OF(X509) *signers, *included_certs;
391
2.44k
    STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
392
2.44k
    PKCS7_SIGNER_INFO *si;
393
2.44k
    PKCS7_ISSUER_AND_SERIAL *ias;
394
2.44k
    X509 *signer;
395
2.44k
    int i;
396
397
2.44k
    if (p7 == NULL) {
398
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
399
0
        return NULL;
400
0
    }
401
402
2.44k
    if (!PKCS7_type_is_signed(p7)) {
403
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
404
0
        return NULL;
405
0
    }
406
2.44k
    included_certs = pkcs7_get0_certificates(p7);
407
408
    /* Collect all the signers together */
409
410
2.44k
    sinfos = PKCS7_get_signer_info(p7);
411
412
2.44k
    if (sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
413
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_SIGNERS);
414
0
        return 0;
415
0
    }
416
417
2.44k
    if ((signers = sk_X509_new_null()) == NULL) {
418
0
        ERR_raise(ERR_LIB_PKCS7, ERR_R_CRYPTO_LIB);
419
0
        return NULL;
420
0
    }
421
422
4.94k
    for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) {
423
2.57k
        si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
424
2.57k
        ias = si->issuer_and_serial;
425
2.57k
        signer = NULL;
426
        /* If any certificates passed they take priority */
427
2.57k
        signer = X509_find_by_issuer_and_serial(certs,
428
2.57k
            ias->issuer, ias->serial);
429
2.57k
        if (signer == NULL && (flags & PKCS7_NOINTERN) == 0)
430
2.57k
            signer = X509_find_by_issuer_and_serial(included_certs,
431
2.57k
                ias->issuer, ias->serial);
432
2.57k
        if (signer == NULL) {
433
80
            ERR_raise(ERR_LIB_PKCS7, PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
434
80
            sk_X509_free(signers);
435
80
            return 0;
436
80
        }
437
438
2.49k
        if (!sk_X509_push(signers, signer)) {
439
0
            sk_X509_free(signers);
440
0
            return NULL;
441
0
        }
442
2.49k
    }
443
2.36k
    return signers;
444
2.44k
}
445
446
/* Build a complete PKCS#7 enveloped data */
447
448
PKCS7 *PKCS7_encrypt_ex(const STACK_OF(X509) *certs, BIO *in,
449
    const EVP_CIPHER *cipher, int flags,
450
    OSSL_LIB_CTX *libctx, const char *propq)
451
0
{
452
0
    PKCS7 *p7;
453
0
    BIO *p7bio = NULL;
454
0
    int i;
455
0
    X509 *x509;
456
457
0
    if ((p7 = PKCS7_new_ex(libctx, propq)) == NULL) {
458
0
        ERR_raise(ERR_LIB_PKCS7, ERR_R_PKCS7_LIB);
459
0
        return NULL;
460
0
    }
461
462
0
    if (!PKCS7_set_type(p7, NID_pkcs7_enveloped))
463
0
        goto err;
464
0
    if (!PKCS7_set_cipher(p7, cipher)) {
465
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ERROR_SETTING_CIPHER);
466
0
        goto err;
467
0
    }
468
469
0
    for (i = 0; i < sk_X509_num(certs); i++) {
470
0
        x509 = sk_X509_value(certs, i);
471
0
        if (!PKCS7_add_recipient(p7, x509)) {
472
0
            ERR_raise(ERR_LIB_PKCS7, PKCS7_R_ERROR_ADDING_RECIPIENT);
473
0
            goto err;
474
0
        }
475
0
    }
476
477
0
    if (flags & PKCS7_STREAM)
478
0
        return p7;
479
480
0
    if (PKCS7_final(p7, in, flags))
481
0
        return p7;
482
483
0
err:
484
485
0
    BIO_free_all(p7bio);
486
0
    PKCS7_free(p7);
487
0
    return NULL;
488
0
}
489
490
PKCS7 *PKCS7_encrypt(const STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, int flags)
491
0
{
492
0
    return PKCS7_encrypt_ex(certs, in, cipher, flags, NULL, NULL);
493
0
}
494
495
int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
496
0
{
497
0
    BIO *tmpmem;
498
0
    int ret = 0, i;
499
0
    char *buf = NULL;
500
501
0
    if (p7 == NULL) {
502
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER);
503
0
        return 0;
504
0
    }
505
506
0
    if (!PKCS7_type_is_enveloped(p7)
507
0
        && !PKCS7_type_is_signedAndEnveloped(p7)) {
508
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_WRONG_CONTENT_TYPE);
509
0
        return 0;
510
0
    }
511
512
0
    if (cert && !X509_check_private_key(cert, pkey)) {
513
0
        ERR_raise(ERR_LIB_PKCS7,
514
0
            PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
515
0
        return 0;
516
0
    }
517
518
0
    if ((tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert)) == NULL) {
519
0
        ERR_raise(ERR_LIB_PKCS7, PKCS7_R_DECRYPT_ERROR);
520
0
        return 0;
521
0
    }
522
523
0
    if (flags & PKCS7_TEXT) {
524
0
        BIO *tmpbuf, *bread;
525
        /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
526
0
        if ((tmpbuf = BIO_new(BIO_f_buffer())) == NULL) {
527
0
            ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
528
0
            BIO_free_all(tmpmem);
529
0
            return 0;
530
0
        }
531
0
        if ((bread = BIO_push(tmpbuf, tmpmem)) == NULL) {
532
0
            ERR_raise(ERR_LIB_PKCS7, ERR_R_BIO_LIB);
533
0
            BIO_free_all(tmpbuf);
534
0
            BIO_free_all(tmpmem);
535
0
            return 0;
536
0
        }
537
0
        ret = SMIME_text(bread, data);
538
0
        if (ret > 0 && BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
539
0
            if (BIO_get_cipher_status(tmpmem) <= 0)
540
0
                ret = 0;
541
0
        }
542
0
        BIO_free_all(bread);
543
0
        return ret;
544
0
    }
545
0
    if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL)
546
0
        goto err;
547
0
    for (;;) {
548
0
        i = BIO_read(tmpmem, buf, BUFFERSIZE);
549
0
        if (i <= 0) {
550
0
            ret = 1;
551
0
            if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
552
0
                if (BIO_get_cipher_status(tmpmem) <= 0)
553
0
                    ret = 0;
554
0
            }
555
556
0
            break;
557
0
        }
558
0
        if (BIO_write(data, buf, i) != i) {
559
0
            break;
560
0
        }
561
0
    }
562
0
err:
563
0
    OPENSSL_free(buf);
564
0
    BIO_free_all(tmpmem);
565
0
    return ret;
566
0
}