Coverage Report

Created: 2025-07-11 07:06

/src/nss/lib/pkcs7/p7common.c
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
/*
6
 * PKCS7 implementation -- the exported parts that are used whether
7
 * creating or decoding.
8
 */
9
10
#include "p7local.h"
11
12
#include "cert.h"
13
#include "secitem.h"
14
#include "secoid.h"
15
#include "pk11func.h"
16
17
/*
18
 * Find out (saving pointer to lookup result for future reference)
19
 * and return the inner content type.
20
 */
21
SECOidTag
22
SEC_PKCS7ContentType(SEC_PKCS7ContentInfo *cinfo)
23
0
{
24
0
    if (cinfo->contentTypeTag == NULL)
25
0
        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
26
27
0
    if (cinfo->contentTypeTag == NULL)
28
0
        return SEC_OID_UNKNOWN;
29
30
0
    return cinfo->contentTypeTag->offset;
31
0
}
32
33
/*
34
 * Destroy a PKCS7 contentInfo and all of its sub-pieces.
35
 */
36
void
37
SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo)
38
0
{
39
0
    SECOidTag kind;
40
0
    CERTCertificate **certs;
41
0
    CERTCertificateList **certlists;
42
0
    SEC_PKCS7SignerInfo **signerinfos;
43
0
    SEC_PKCS7RecipientInfo **recipientinfos;
44
45
0
    PORT_Assert(cinfo->refCount > 0);
46
0
    if (cinfo->refCount <= 0)
47
0
        return;
48
49
0
    cinfo->refCount--;
50
0
    if (cinfo->refCount > 0)
51
0
        return;
52
53
0
    certs = NULL;
54
0
    certlists = NULL;
55
0
    recipientinfos = NULL;
56
0
    signerinfos = NULL;
57
58
0
    kind = SEC_PKCS7ContentType(cinfo);
59
0
    switch (kind) {
60
0
        case SEC_OID_PKCS7_ENVELOPED_DATA: {
61
0
            SEC_PKCS7EnvelopedData *edp;
62
63
0
            edp = cinfo->content.envelopedData;
64
0
            if (edp != NULL) {
65
0
                recipientinfos = edp->recipientInfos;
66
0
            }
67
0
        } break;
68
0
        case SEC_OID_PKCS7_SIGNED_DATA: {
69
0
            SEC_PKCS7SignedData *sdp;
70
71
0
            sdp = cinfo->content.signedData;
72
0
            if (sdp != NULL) {
73
0
                certs = sdp->certs;
74
0
                certlists = sdp->certLists;
75
0
                signerinfos = sdp->signerInfos;
76
0
            }
77
0
        } break;
78
0
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: {
79
0
            SEC_PKCS7SignedAndEnvelopedData *saedp;
80
81
0
            saedp = cinfo->content.signedAndEnvelopedData;
82
0
            if (saedp != NULL) {
83
0
                certs = saedp->certs;
84
0
                certlists = saedp->certLists;
85
0
                recipientinfos = saedp->recipientInfos;
86
0
                signerinfos = saedp->signerInfos;
87
0
                if (saedp->sigKey != NULL)
88
0
                    PK11_FreeSymKey(saedp->sigKey);
89
0
            }
90
0
        } break;
91
0
        default:
92
            /* XXX Anything else that needs to be "manually" freed/destroyed? */
93
0
            break;
94
0
    }
95
96
0
    if (certs != NULL) {
97
0
        CERTCertificate *cert;
98
99
0
        while ((cert = *certs++) != NULL) {
100
0
            CERT_DestroyCertificate(cert);
101
0
        }
102
0
    }
103
104
0
    if (certlists != NULL) {
105
0
        CERTCertificateList *certlist;
106
107
0
        while ((certlist = *certlists++) != NULL) {
108
0
            CERT_DestroyCertificateList(certlist);
109
0
        }
110
0
    }
111
112
0
    if (recipientinfos != NULL) {
113
0
        SEC_PKCS7RecipientInfo *ri;
114
115
0
        while ((ri = *recipientinfos++) != NULL) {
116
0
            if (ri->cert != NULL)
117
0
                CERT_DestroyCertificate(ri->cert);
118
0
        }
119
0
    }
120
121
0
    if (signerinfos != NULL) {
122
0
        SEC_PKCS7SignerInfo *si;
123
124
0
        while ((si = *signerinfos++) != NULL) {
125
0
            if (si->cert != NULL)
126
0
                CERT_DestroyCertificate(si->cert);
127
0
            if (si->certList != NULL)
128
0
                CERT_DestroyCertificateList(si->certList);
129
0
        }
130
0
    }
131
132
0
    if (cinfo->poolp != NULL) {
133
0
        PORT_FreeArena(cinfo->poolp, PR_FALSE); /* XXX clear it? */
134
0
    }
135
0
}
136
137
/*
138
 * Return a copy of the given contentInfo.  The copy may be virtual
139
 * or may be real -- either way, the result needs to be passed to
140
 * SEC_PKCS7DestroyContentInfo later (as does the original).
141
 */
142
SEC_PKCS7ContentInfo *
143
SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo)
144
0
{
145
0
    if (cinfo == NULL)
146
0
        return NULL;
147
148
0
    PORT_Assert(cinfo->refCount > 0);
149
150
0
    if (cinfo->created) {
151
        /*
152
         * Want to do a real copy of these; otherwise subsequent
153
         * changes made to either copy are likely to be a surprise.
154
         * XXX I suspect that this will not actually be called for yet,
155
         * which is why the assert, so to notice if it is...
156
         */
157
0
        PORT_Assert(0);
158
        /*
159
         * XXX Create a new pool here, and copy everything from
160
         * within.  For cert stuff, need to call the appropriate
161
         * copy functions, etc.
162
         */
163
0
    }
164
165
0
    cinfo->refCount++;
166
0
    return cinfo;
167
0
}
168
169
/*
170
 * Return a pointer to the actual content.  In the case of those types
171
 * which are encrypted, this returns the *plain* content.
172
 * XXX Needs revisiting if/when we handle nested encrypted types.
173
 */
174
SECItem *
175
SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo)
176
0
{
177
0
    SECOidTag kind;
178
179
0
    kind = SEC_PKCS7ContentType(cinfo);
180
0
    switch (kind) {
181
0
        case SEC_OID_PKCS7_DATA:
182
0
            return cinfo->content.data;
183
0
        case SEC_OID_PKCS7_DIGESTED_DATA: {
184
0
            SEC_PKCS7DigestedData *digd;
185
186
0
            digd = cinfo->content.digestedData;
187
0
            if (digd == NULL)
188
0
                break;
189
0
            return SEC_PKCS7GetContent(&(digd->contentInfo));
190
0
        }
191
0
        case SEC_OID_PKCS7_ENCRYPTED_DATA: {
192
0
            SEC_PKCS7EncryptedData *encd;
193
194
0
            encd = cinfo->content.encryptedData;
195
0
            if (encd == NULL)
196
0
                break;
197
0
            return &(encd->encContentInfo.plainContent);
198
0
        }
199
0
        case SEC_OID_PKCS7_ENVELOPED_DATA: {
200
0
            SEC_PKCS7EnvelopedData *envd;
201
202
0
            envd = cinfo->content.envelopedData;
203
0
            if (envd == NULL)
204
0
                break;
205
0
            return &(envd->encContentInfo.plainContent);
206
0
        }
207
0
        case SEC_OID_PKCS7_SIGNED_DATA: {
208
0
            SEC_PKCS7SignedData *sigd;
209
210
0
            sigd = cinfo->content.signedData;
211
0
            if (sigd == NULL)
212
0
                break;
213
0
            return SEC_PKCS7GetContent(&(sigd->contentInfo));
214
0
        }
215
0
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: {
216
0
            SEC_PKCS7SignedAndEnvelopedData *saed;
217
218
0
            saed = cinfo->content.signedAndEnvelopedData;
219
0
            if (saed == NULL)
220
0
                break;
221
0
            return &(saed->encContentInfo.plainContent);
222
0
        }
223
0
        default:
224
0
            PORT_Assert(0);
225
0
            break;
226
0
    }
227
228
0
    return NULL;
229
0
}
230
231
/*
232
 * XXX Fix the placement and formatting of the
233
 * following routines (i.e. make them consistent with the rest of
234
 * the pkcs7 code -- I think some/many belong in other files and
235
 * they all need a formatting/style rehaul)
236
 */
237
238
/* retrieve the algorithm identifier for encrypted data.
239
 * the identifier returned is a copy of the algorithm identifier
240
 * in the content info and needs to be freed after being used.
241
 *
242
 *   cinfo is the content info for which to retrieve the
243
 *     encryption algorithm.
244
 *
245
 * if the content info is not encrypted data or an error
246
 * occurs NULL is returned.
247
 */
248
SECAlgorithmID *
249
SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo)
250
0
{
251
0
    SECAlgorithmID *alg = 0;
252
0
    switch (SEC_PKCS7ContentType(cinfo)) {
253
0
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
254
0
            alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg;
255
0
            break;
256
0
        case SEC_OID_PKCS7_ENVELOPED_DATA:
257
0
            alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg;
258
0
            break;
259
0
        case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA:
260
0
            alg = &cinfo->content.signedAndEnvelopedData
261
0
                       ->encContentInfo.contentEncAlg;
262
0
            break;
263
0
        default:
264
0
            alg = 0;
265
0
            break;
266
0
    }
267
268
0
    return alg;
269
0
}
270
271
/* set the content of the content info.  For data content infos,
272
 * the data is set.  For encrytped content infos, the plainContent
273
 * is set, and is expected to be encrypted later.
274
 *
275
 * cinfo is the content info where the data will be set
276
 *
277
 * buf is a buffer of the data to set
278
 *
279
 * len is the length of the data being set.
280
 *
281
 * in the event of an error, SECFailure is returned.  SECSuccess
282
 * indicates the content was successfully set.
283
 */
284
SECStatus
285
SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo,
286
                    const char *buf,
287
                    unsigned long len)
288
0
{
289
0
    SECOidTag cinfo_type;
290
0
    SECStatus rv;
291
0
    SECItem content;
292
0
    SECOidData *contentTypeTag = NULL;
293
294
0
    content.type = siBuffer;
295
0
    content.data = (unsigned char *)buf;
296
0
    content.len = len;
297
298
0
    cinfo_type = SEC_PKCS7ContentType(cinfo);
299
300
    /* set inner content */
301
0
    switch (cinfo_type) {
302
0
        case SEC_OID_PKCS7_SIGNED_DATA:
303
0
            if (content.len > 0) {
304
                /* we "leak" the old content here, but as it's all in the pool */
305
                /* it does not really matter */
306
307
                /* create content item if necessary */
308
0
                if (cinfo->content.signedData->contentInfo.content.data == NULL)
309
0
                    cinfo->content.signedData->contentInfo.content.data = SECITEM_AllocItem(cinfo->poolp, NULL, 0);
310
0
                rv = SECITEM_CopyItem(cinfo->poolp,
311
0
                                      cinfo->content.signedData->contentInfo.content.data,
312
0
                                      &content);
313
0
            } else {
314
0
                cinfo->content.signedData->contentInfo.content.data->data = NULL;
315
0
                cinfo->content.signedData->contentInfo.content.data->len = 0;
316
0
                rv = SECSuccess;
317
0
            }
318
0
            if (rv == SECFailure)
319
0
                goto loser;
320
321
0
            break;
322
0
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
323
            /* XXX this forces the inner content type to be "data" */
324
            /* do we really want to override without asking or reason? */
325
0
            contentTypeTag = SECOID_FindOIDByTag(SEC_OID_PKCS7_DATA);
326
0
            if (contentTypeTag == NULL)
327
0
                goto loser;
328
0
            rv = SECITEM_CopyItem(cinfo->poolp,
329
0
                                  &(cinfo->content.encryptedData->encContentInfo.contentType),
330
0
                                  &(contentTypeTag->oid));
331
0
            if (rv == SECFailure)
332
0
                goto loser;
333
0
            if (content.len > 0) {
334
0
                rv = SECITEM_CopyItem(cinfo->poolp,
335
0
                                      &(cinfo->content.encryptedData->encContentInfo.plainContent),
336
0
                                      &content);
337
0
            } else {
338
0
                cinfo->content.encryptedData->encContentInfo.plainContent.data = NULL;
339
0
                cinfo->content.encryptedData->encContentInfo.encContent.data = NULL;
340
0
                cinfo->content.encryptedData->encContentInfo.plainContent.len = 0;
341
0
                cinfo->content.encryptedData->encContentInfo.encContent.len = 0;
342
0
                rv = SECSuccess;
343
0
            }
344
0
            if (rv == SECFailure)
345
0
                goto loser;
346
0
            break;
347
0
        case SEC_OID_PKCS7_DATA:
348
0
            cinfo->content.data = (SECItem *)PORT_ArenaZAlloc(cinfo->poolp,
349
0
                                                              sizeof(SECItem));
350
0
            if (cinfo->content.data == NULL)
351
0
                goto loser;
352
0
            if (content.len > 0) {
353
0
                rv = SECITEM_CopyItem(cinfo->poolp,
354
0
                                      cinfo->content.data, &content);
355
0
            } else {
356
                /* handle case with NULL content */
357
0
                rv = SECSuccess;
358
0
            }
359
0
            if (rv == SECFailure)
360
0
                goto loser;
361
0
            break;
362
0
        default:
363
0
            goto loser;
364
0
    }
365
366
0
    return SECSuccess;
367
368
0
loser:
369
370
0
    return SECFailure;
371
0
}
372
373
/* the content of an encrypted data content info is encrypted.
374
 * it is assumed that for encrypted data, that the data has already
375
 * been set and is in the "plainContent" field of the content info.
376
 *
377
 * cinfo is the content info to encrypt
378
 *
379
 * key is the key with which to perform the encryption.  if the
380
 *     algorithm is a password based encryption algorithm, the
381
 *     key is actually a password which will be processed per
382
 *     PKCS #5.
383
 *
384
 * in the event of an error, SECFailure is returned.  SECSuccess
385
 * indicates a success.
386
 */
387
SECStatus
388
SEC_PKCS7EncryptContents(PLArenaPool *poolp,
389
                         SEC_PKCS7ContentInfo *cinfo,
390
                         SECItem *key,
391
                         void *wincx)
392
0
{
393
0
    SECAlgorithmID *algid = NULL;
394
0
    SECItem *src;
395
0
    SECItem *dest;
396
0
    SECItem *blocked_data = NULL;
397
0
    void *mark;
398
0
    void *cx;
399
0
    PK11SymKey *eKey = NULL;
400
0
    PK11SlotInfo *slot = NULL;
401
402
0
    CK_MECHANISM_TYPE cryptoMechType;
403
0
    int bs;
404
0
    SECStatus rv = SECFailure;
405
0
    SECItem *c_param = NULL;
406
407
0
    if ((cinfo == NULL) || (key == NULL))
408
0
        return SECFailure;
409
410
0
    if (SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
411
0
        return SECFailure;
412
413
0
    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
414
0
    if (algid == NULL)
415
0
        return SECFailure;
416
417
0
    if (poolp == NULL)
418
0
        poolp = cinfo->poolp;
419
420
0
    mark = PORT_ArenaMark(poolp);
421
422
0
    src = &cinfo->content.encryptedData->encContentInfo.plainContent;
423
0
    dest = &cinfo->content.encryptedData->encContentInfo.encContent;
424
0
    dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, (src->len + 64));
425
0
    dest->len = (src->len + 64);
426
0
    if (dest->data == NULL) {
427
0
        rv = SECFailure;
428
0
        goto loser;
429
0
    }
430
431
0
    slot = PK11_GetInternalKeySlot();
432
0
    if (slot == NULL) {
433
0
        rv = SECFailure;
434
0
        goto loser;
435
0
    }
436
437
0
    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
438
0
    if (eKey == NULL) {
439
0
        rv = SECFailure;
440
0
        goto loser;
441
0
    }
442
443
0
    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
444
0
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
445
0
        rv = SECFailure;
446
0
        goto loser;
447
0
    }
448
449
    /* block according to PKCS 8 */
450
0
    bs = PK11_GetBlockSize(cryptoMechType, c_param);
451
0
    rv = SECSuccess;
452
0
    if (bs) {
453
0
        char pad_char;
454
0
        pad_char = (char)(bs - (src->len % bs));
455
0
        if (src->len % bs) {
456
0
            rv = SECSuccess;
457
0
            blocked_data = PK11_BlockData(src, bs);
458
0
            if (blocked_data) {
459
0
                PORT_Memset((blocked_data->data + blocked_data->len - (int)pad_char),
460
0
                            pad_char, (int)pad_char);
461
0
            } else {
462
0
                rv = SECFailure;
463
0
                goto loser;
464
0
            }
465
0
        } else {
466
0
            blocked_data = SECITEM_DupItem(src);
467
0
            if (blocked_data) {
468
0
                blocked_data->data = (unsigned char *)PORT_Realloc(
469
0
                    blocked_data->data,
470
0
                    blocked_data->len + bs);
471
0
                if (blocked_data->data) {
472
0
                    blocked_data->len += bs;
473
0
                    PORT_Memset((blocked_data->data + src->len), (char)bs, bs);
474
0
                } else {
475
0
                    rv = SECFailure;
476
0
                    goto loser;
477
0
                }
478
0
            } else {
479
0
                rv = SECFailure;
480
0
                goto loser;
481
0
            }
482
0
        }
483
0
    } else {
484
0
        blocked_data = SECITEM_DupItem(src);
485
0
        if (!blocked_data) {
486
0
            rv = SECFailure;
487
0
            goto loser;
488
0
        }
489
0
    }
490
491
0
    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
492
0
                                    eKey, c_param);
493
0
    if (cx == NULL) {
494
0
        rv = SECFailure;
495
0
        goto loser;
496
0
    }
497
498
0
    rv = PK11_CipherOp((PK11Context *)cx, dest->data, (int *)(&dest->len),
499
0
                       (int)(src->len + 64), blocked_data->data,
500
0
                       (int)blocked_data->len);
501
0
    PK11_DestroyContext((PK11Context *)cx, PR_TRUE);
502
503
0
loser:
504
    /* let success fall through */
505
0
    if (blocked_data != NULL)
506
0
        SECITEM_ZfreeItem(blocked_data, PR_TRUE);
507
508
0
    if (rv == SECFailure)
509
0
        PORT_ArenaRelease(poolp, mark);
510
0
    else
511
0
        PORT_ArenaUnmark(poolp, mark);
512
513
0
    if (eKey != NULL)
514
0
        PK11_FreeSymKey(eKey);
515
516
0
    if (slot != NULL)
517
0
        PK11_FreeSlot(slot);
518
519
0
    if (c_param != NULL)
520
0
        SECITEM_ZfreeItem(c_param, PR_TRUE);
521
522
0
    return rv;
523
0
}
524
525
/* the content of an encrypted data content info is decrypted.
526
 * it is assumed that for encrypted data, that the data has already
527
 * been set and is in the "encContent" field of the content info.
528
 *
529
 * cinfo is the content info to decrypt
530
 *
531
 * key is the key with which to perform the decryption.  if the
532
 *     algorithm is a password based encryption algorithm, the
533
 *     key is actually a password which will be processed per
534
 *     PKCS #5.
535
 *
536
 * in the event of an error, SECFailure is returned.  SECSuccess
537
 * indicates a success.
538
 */
539
SECStatus
540
SEC_PKCS7DecryptContents(PLArenaPool *poolp,
541
                         SEC_PKCS7ContentInfo *cinfo,
542
                         SECItem *key,
543
                         void *wincx)
544
0
{
545
0
    SECAlgorithmID *algid = NULL;
546
0
    SECStatus rv = SECFailure;
547
0
    SECItem *dest, *src;
548
0
    void *mark;
549
550
0
    PK11SymKey *eKey = NULL;
551
0
    PK11SlotInfo *slot = NULL;
552
0
    CK_MECHANISM_TYPE cryptoMechType;
553
0
    void *cx;
554
0
    SECItem *c_param = NULL;
555
0
    int bs;
556
557
0
    if ((cinfo == NULL) || (key == NULL))
558
0
        return SECFailure;
559
560
0
    if (SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
561
0
        return SECFailure;
562
563
0
    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);
564
0
    if (algid == NULL)
565
0
        return SECFailure;
566
567
0
    if (poolp == NULL)
568
0
        poolp = cinfo->poolp;
569
570
0
    mark = PORT_ArenaMark(poolp);
571
572
0
    src = &cinfo->content.encryptedData->encContentInfo.encContent;
573
0
    dest = &cinfo->content.encryptedData->encContentInfo.plainContent;
574
0
    dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, (src->len + 64));
575
0
    dest->len = (src->len + 64);
576
0
    if (dest->data == NULL) {
577
0
        rv = SECFailure;
578
0
        goto loser;
579
0
    }
580
581
0
    slot = PK11_GetInternalKeySlot();
582
0
    if (slot == NULL) {
583
0
        rv = SECFailure;
584
0
        goto loser;
585
0
    }
586
587
0
    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
588
0
    if (eKey == NULL) {
589
0
        rv = SECFailure;
590
0
        goto loser;
591
0
    }
592
593
0
    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
594
0
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
595
0
        rv = SECFailure;
596
0
        goto loser;
597
0
    }
598
599
0
    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
600
0
                                    eKey, c_param);
601
0
    if (cx == NULL) {
602
0
        rv = SECFailure;
603
0
        goto loser;
604
0
    }
605
606
0
    rv = PK11_CipherOp((PK11Context *)cx, dest->data, (int *)(&dest->len),
607
0
                       (int)(src->len + 64), src->data, (int)src->len);
608
0
    PK11_DestroyContext((PK11Context *)cx, PR_TRUE);
609
610
0
    bs = PK11_GetBlockSize(cryptoMechType, c_param);
611
0
    if (bs) {
612
        /* check for proper badding in block algorithms.  this assumes
613
         * RC2 cbc or a DES cbc variant.  and the padding is thus defined
614
         */
615
0
        if (((int)dest->data[dest->len - 1] <= bs) &&
616
0
            ((int)dest->data[dest->len - 1] > 0)) {
617
0
            dest->len -= (int)dest->data[dest->len - 1];
618
0
        } else {
619
0
            rv = SECFailure;
620
            /* set an error ? */
621
0
        }
622
0
    }
623
624
0
loser:
625
    /* let success fall through */
626
0
    if (rv == SECFailure)
627
0
        PORT_ArenaRelease(poolp, mark);
628
0
    else
629
0
        PORT_ArenaUnmark(poolp, mark);
630
631
0
    if (eKey != NULL)
632
0
        PK11_FreeSymKey(eKey);
633
634
0
    if (slot != NULL)
635
0
        PK11_FreeSlot(slot);
636
637
0
    if (c_param != NULL)
638
0
        SECITEM_ZfreeItem(c_param, PR_TRUE);
639
640
0
    return rv;
641
0
}
642
643
SECItem **
644
SEC_PKCS7GetCertificateList(SEC_PKCS7ContentInfo *cinfo)
645
0
{
646
0
    switch (SEC_PKCS7ContentType(cinfo)) {
647
0
        case SEC_OID_PKCS7_SIGNED_DATA:
648
0
            return cinfo->content.signedData->rawCerts;
649
0
            break;
650
0
        default:
651
0
            return NULL;
652
0
            break;
653
0
    }
654
0
}
655
656
int
657
SEC_PKCS7GetKeyLength(SEC_PKCS7ContentInfo *cinfo)
658
0
{
659
0
    if (cinfo->contentTypeTag->offset == SEC_OID_PKCS7_ENVELOPED_DATA)
660
0
        return cinfo->content.envelopedData->encContentInfo.keysize;
661
0
    else
662
0
        return 0;
663
0
}