Coverage Report

Created: 2025-08-28 06:13

/src/nss/lib/smime/cmscinfo.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
 * CMS contentInfo methods.
7
 */
8
9
#include "cmslocal.h"
10
11
#include "pk11func.h"
12
#include "secitem.h"
13
#include "secoid.h"
14
#include "secerr.h"
15
16
/*
17
 * NSS_CMSContentInfo_Create - create a content info
18
 *
19
 * version is set in the _Finalize procedures for each content type
20
 */
21
SECStatus
22
NSS_CMSContentInfo_Private_Init(NSSCMSContentInfo *cinfo)
23
6.47k
{
24
6.47k
    if (cinfo->privateInfo) {
25
0
        return SECSuccess;
26
0
    }
27
6.47k
    cinfo->privateInfo = PORT_ZNew(NSSCMSContentInfoPrivate);
28
6.47k
    return (cinfo->privateInfo) ? SECSuccess : SECFailure;
29
6.47k
}
30
31
static void
32
nss_cmsContentInfo_private_destroy(NSSCMSContentInfoPrivate *privateInfo)
33
6.47k
{
34
6.47k
    if (privateInfo->digcx) {
35
        /* must destroy digest objects */
36
1.77k
        NSS_CMSDigestContext_Cancel(privateInfo->digcx);
37
1.77k
        privateInfo->digcx = NULL;
38
1.77k
    }
39
6.47k
    if (privateInfo->ciphcx) {
40
0
        NSS_CMSCipherContext_Destroy(privateInfo->ciphcx);
41
0
        privateInfo->ciphcx = NULL;
42
0
    }
43
6.47k
    PORT_Free(privateInfo);
44
6.47k
}
45
46
/*
47
 * NSS_CMSContentInfo_Destroy - destroy a CMS contentInfo and all of its sub-pieces.
48
 */
49
void
50
NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo)
51
7.47k
{
52
7.47k
    SECOidTag kind;
53
54
7.47k
    if (cinfo == NULL) {
55
0
        return;
56
0
    }
57
58
7.47k
    kind = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
59
7.47k
    switch (kind) {
60
727
        case SEC_OID_PKCS7_ENVELOPED_DATA:
61
727
            NSS_CMSEnvelopedData_Destroy(cinfo->content.envelopedData);
62
727
            break;
63
2.40k
        case SEC_OID_PKCS7_SIGNED_DATA:
64
2.40k
            NSS_CMSSignedData_Destroy(cinfo->content.signedData);
65
2.40k
            break;
66
20
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
67
20
            NSS_CMSEncryptedData_Destroy(cinfo->content.encryptedData);
68
20
            break;
69
77
        case SEC_OID_PKCS7_DIGESTED_DATA:
70
77
            NSS_CMSDigestedData_Destroy(cinfo->content.digestedData);
71
77
            break;
72
4.24k
        default:
73
4.24k
            NSS_CMSGenericWrapperData_Destroy(kind, cinfo->content.genericData);
74
            /* XXX Anything else that needs to be "manually" freed/destroyed? */
75
4.24k
            break;
76
7.47k
    }
77
7.47k
    if (cinfo->privateInfo) {
78
6.47k
        nss_cmsContentInfo_private_destroy(cinfo->privateInfo);
79
6.47k
        cinfo->privateInfo = NULL;
80
6.47k
    }
81
7.47k
    if (cinfo->bulkkey) {
82
0
        PK11_FreeSymKey(cinfo->bulkkey);
83
0
    }
84
7.47k
}
85
86
/*
87
 * NSS_CMSContentInfo_GetChildContentInfo - get content's contentInfo (if it exists)
88
 */
89
NSSCMSContentInfo *
90
NSS_CMSContentInfo_GetChildContentInfo(NSSCMSContentInfo *cinfo)
91
98
{
92
98
    NSSCMSContentInfo *ccinfo = NULL;
93
94
98
    if (cinfo == NULL) {
95
0
        return NULL;
96
0
    }
97
98
98
    SECOidTag tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
99
98
    switch (tag) {
100
61
        case SEC_OID_PKCS7_SIGNED_DATA:
101
61
            if (cinfo->content.signedData != NULL) {
102
61
                ccinfo = &(cinfo->content.signedData->contentInfo);
103
61
            }
104
61
            break;
105
3
        case SEC_OID_PKCS7_ENVELOPED_DATA:
106
3
            if (cinfo->content.envelopedData != NULL) {
107
2
                ccinfo = &(cinfo->content.envelopedData->contentInfo);
108
2
            }
109
3
            break;
110
4
        case SEC_OID_PKCS7_DIGESTED_DATA:
111
4
            if (cinfo->content.digestedData != NULL) {
112
3
                ccinfo = &(cinfo->content.digestedData->contentInfo);
113
3
            }
114
4
            break;
115
2
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
116
2
            if (cinfo->content.encryptedData != NULL) {
117
1
                ccinfo = &(cinfo->content.encryptedData->contentInfo);
118
1
            }
119
2
            break;
120
5
        case SEC_OID_PKCS7_DATA:
121
28
        default:
122
28
            if (NSS_CMSType_IsWrapper(tag)) {
123
0
                if (cinfo->content.genericData != NULL) {
124
0
                    ccinfo = &(cinfo->content.genericData->contentInfo);
125
0
                }
126
0
            }
127
28
            break;
128
98
    }
129
98
    if (ccinfo && !ccinfo->privateInfo) {
130
13
        NSS_CMSContentInfo_Private_Init(ccinfo);
131
13
    }
132
98
    return ccinfo;
133
98
}
134
135
SECStatus
136
NSS_CMSContentInfo_SetDontStream(NSSCMSContentInfo *cinfo, PRBool dontStream)
137
0
{
138
0
    SECStatus rv;
139
0
    if (cinfo == NULL) {
140
0
        return SECFailure;
141
0
    }
142
143
0
    rv = NSS_CMSContentInfo_Private_Init(cinfo);
144
0
    if (rv != SECSuccess) {
145
        /* default is streaming, failure to get ccinfo will not effect this */
146
0
        return dontStream ? SECFailure : SECSuccess;
147
0
    }
148
0
    cinfo->privateInfo->dontStream = dontStream;
149
0
    return SECSuccess;
150
0
}
151
152
/*
153
 * NSS_CMSContentInfo_SetContent - set content type & content
154
 */
155
SECStatus
156
NSS_CMSContentInfo_SetContent(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo,
157
                              SECOidTag type, void *ptr)
158
0
{
159
0
    SECStatus rv;
160
0
    if (cinfo == NULL || cmsg == NULL) {
161
0
        return SECFailure;
162
0
    }
163
164
0
    cinfo->contentTypeTag = SECOID_FindOIDByTag(type);
165
0
    if (cinfo->contentTypeTag == NULL) {
166
0
        return SECFailure;
167
0
    }
168
169
    /* do not copy the oid, just create a reference */
170
0
    rv = SECITEM_CopyItem(cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid));
171
0
    if (rv != SECSuccess) {
172
0
        return SECFailure;
173
0
    }
174
175
0
    cinfo->content.pointer = ptr;
176
177
0
    if (NSS_CMSType_IsData(type) && ptr) {
178
0
        cinfo->rawContent = ptr;
179
0
    } else {
180
        /* as we always have some inner data,
181
         * we need to set it to something, just to fool the encoder enough to work on it
182
         * and get us into nss_cms_encoder_notify at that point */
183
0
        cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1);
184
0
        if (cinfo->rawContent == NULL) {
185
0
            PORT_SetError(SEC_ERROR_NO_MEMORY);
186
0
            return SECFailure;
187
0
        }
188
0
    }
189
190
0
    return SECSuccess;
191
0
}
192
193
/*
194
 * NSS_CMSContentInfo_SetContent_XXXX - typesafe wrappers for NSS_CMSContentInfo_SetContent
195
 */
196
197
/*
198
 * data == NULL -> pass in data via NSS_CMSEncoder_Update
199
 * data != NULL -> take this data
200
 */
201
SECStatus
202
NSS_CMSContentInfo_SetContent_Data(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo,
203
                                   SECItem *data, PRBool detached)
204
0
{
205
0
    if (NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) {
206
0
        return SECFailure;
207
0
    }
208
0
    if (detached) {
209
0
        cinfo->rawContent = NULL;
210
0
    }
211
212
0
    return SECSuccess;
213
0
}
214
215
SECStatus
216
NSS_CMSContentInfo_SetContent_SignedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo,
217
                                         NSSCMSSignedData *sigd)
218
0
{
219
0
    return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd);
220
0
}
221
222
SECStatus
223
NSS_CMSContentInfo_SetContent_EnvelopedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo,
224
                                            NSSCMSEnvelopedData *envd)
225
0
{
226
0
    return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd);
227
0
}
228
229
SECStatus
230
NSS_CMSContentInfo_SetContent_DigestedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo,
231
                                           NSSCMSDigestedData *digd)
232
0
{
233
0
    return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd);
234
0
}
235
236
SECStatus
237
NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo,
238
                                            NSSCMSEncryptedData *encd)
239
0
{
240
0
    return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
241
0
}
242
243
/*
244
 * NSS_CMSContentInfo_GetContent - get pointer to inner content
245
 *
246
 * needs to be casted...
247
 */
248
void *
249
NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo)
250
0
{
251
0
    if (cinfo == NULL) {
252
0
        return NULL;
253
0
    }
254
255
0
    SECOidTag tag = cinfo->contentTypeTag
256
0
                        ? cinfo->contentTypeTag->offset
257
0
                        : SEC_OID_UNKNOWN;
258
0
    switch (tag) {
259
0
        case SEC_OID_PKCS7_DATA:
260
0
        case SEC_OID_PKCS7_SIGNED_DATA:
261
0
        case SEC_OID_PKCS7_ENVELOPED_DATA:
262
0
        case SEC_OID_PKCS7_DIGESTED_DATA:
263
0
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
264
0
            return cinfo->content.pointer;
265
0
        default:
266
0
            return NSS_CMSType_IsWrapper(tag) ? cinfo->content.pointer
267
0
                                              : (NSS_CMSType_IsData(tag) ? cinfo->rawContent
268
0
                                                                         : NULL);
269
0
    }
270
0
}
271
272
/*
273
 * NSS_CMSContentInfo_GetInnerContent - get pointer to innermost content
274
 *
275
 * this is typically only called by NSS_CMSMessage_GetContent()
276
 */
277
278
SECItem *
279
NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo)
280
0
{
281
0
    NSSCMSContentInfo *ccinfo;
282
0
    SECOidTag tag;
283
0
    SECItem *pItem = NULL;
284
285
0
    if (cinfo == NULL) {
286
0
        return NULL;
287
0
    }
288
289
0
    tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
290
0
    if (NSS_CMSType_IsData(tag)) {
291
0
        pItem = cinfo->content.data;
292
0
    } else if (NSS_CMSType_IsWrapper(tag)) {
293
0
        ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo);
294
0
        if (ccinfo != NULL) {
295
0
            pItem = NSS_CMSContentInfo_GetContent(ccinfo);
296
0
        }
297
0
    } else {
298
0
        PORT_Assert(0);
299
0
    }
300
301
0
    return pItem;
302
0
}
303
304
/*
305
 * NSS_CMSContentInfo_GetContentType{Tag,OID} - find out (saving pointer to lookup result
306
 * for future reference) and return the inner content type.
307
 */
308
SECOidTag
309
NSS_CMSContentInfo_GetContentTypeTag(NSSCMSContentInfo *cinfo)
310
1.93M
{
311
1.93M
    if (cinfo == NULL) {
312
0
        return SEC_OID_UNKNOWN;
313
0
    }
314
315
1.93M
    if (cinfo->contentTypeTag == NULL)
316
10.2k
        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
317
318
1.93M
    if (cinfo->contentTypeTag == NULL)
319
6.59k
        return SEC_OID_UNKNOWN;
320
321
1.92M
    return cinfo->contentTypeTag->offset;
322
1.93M
}
323
324
SECItem *
325
NSS_CMSContentInfo_GetContentTypeOID(NSSCMSContentInfo *cinfo)
326
0
{
327
0
    if (cinfo == NULL) {
328
0
        return NULL;
329
0
    }
330
331
0
    if (cinfo->contentTypeTag == NULL) {
332
0
        cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
333
0
    }
334
335
0
    if (cinfo->contentTypeTag == NULL) {
336
0
        return NULL;
337
0
    }
338
339
0
    return &(cinfo->contentTypeTag->oid);
340
0
}
341
342
/*
343
 * NSS_CMSContentInfo_GetContentEncAlgTag - find out (saving pointer to lookup result
344
 * for future reference) and return the content encryption algorithm tag.
345
 */
346
SECOidTag
347
NSS_CMSContentInfo_GetContentEncAlgTag(NSSCMSContentInfo *cinfo)
348
0
{
349
0
    if (cinfo == NULL) {
350
0
        return SEC_OID_UNKNOWN;
351
0
    }
352
353
0
    if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN) {
354
0
        cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg));
355
0
    }
356
357
0
    return cinfo->contentEncAlgTag;
358
0
}
359
360
/*
361
 * NSS_CMSContentInfo_GetContentEncAlg - find out and return the content encryption algorithm tag.
362
 */
363
SECAlgorithmID *
364
NSS_CMSContentInfo_GetContentEncAlg(NSSCMSContentInfo *cinfo)
365
5
{
366
5
    if (cinfo == NULL) {
367
0
        return NULL;
368
0
    }
369
370
5
    return &(cinfo->contentEncAlg);
371
5
}
372
373
SECStatus
374
NSS_CMSContentInfo_SetContentEncAlg(PLArenaPool *poolp, NSSCMSContentInfo *cinfo,
375
                                    SECOidTag bulkalgtag, SECItem *parameters, int keysize)
376
0
{
377
0
    SECStatus rv;
378
0
    if (cinfo == NULL) {
379
0
        return SECFailure;
380
0
    }
381
382
0
    rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters);
383
0
    if (rv != SECSuccess) {
384
0
        return SECFailure;
385
0
    }
386
0
    cinfo->keysize = keysize;
387
0
    return SECSuccess;
388
0
}
389
390
SECStatus
391
NSS_CMSContentInfo_SetContentEncAlgID(PLArenaPool *poolp, NSSCMSContentInfo *cinfo,
392
                                      SECAlgorithmID *algid, int keysize)
393
0
{
394
0
    SECStatus rv;
395
0
    if (cinfo == NULL) {
396
0
        return SECFailure;
397
0
    }
398
399
0
    rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid);
400
0
    if (rv != SECSuccess) {
401
0
        return SECFailure;
402
0
    }
403
0
    if (keysize >= 0) {
404
0
        cinfo->keysize = keysize;
405
0
    }
406
0
    return SECSuccess;
407
0
}
408
409
void
410
NSS_CMSContentInfo_SetBulkKey(NSSCMSContentInfo *cinfo, PK11SymKey *bulkkey)
411
0
{
412
0
    if (cinfo == NULL) {
413
0
        return;
414
0
    }
415
416
0
    if (bulkkey == NULL) {
417
0
        cinfo->bulkkey = NULL;
418
0
        cinfo->keysize = 0;
419
0
    } else {
420
0
        cinfo->bulkkey = PK11_ReferenceSymKey(bulkkey);
421
0
        cinfo->keysize = PK11_GetKeyStrength(cinfo->bulkkey, &(cinfo->contentEncAlg));
422
0
    }
423
0
}
424
425
PK11SymKey *
426
NSS_CMSContentInfo_GetBulkKey(NSSCMSContentInfo *cinfo)
427
0
{
428
0
    if (cinfo == NULL || cinfo->bulkkey == NULL) {
429
0
        return NULL;
430
0
    }
431
432
0
    return PK11_ReferenceSymKey(cinfo->bulkkey);
433
0
}
434
435
int
436
NSS_CMSContentInfo_GetBulkKeySize(NSSCMSContentInfo *cinfo)
437
0
{
438
0
    if (cinfo == NULL) {
439
0
        return 0;
440
0
    }
441
442
0
    return cinfo->keysize;
443
0
}