Coverage Report

Created: 2018-09-25 14:53

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