]> git.saurik.com Git - apple/security.git/blame - libsecurity_smime/lib/cmscinfo.c
Security-58286.200.222.tar.gz
[apple/security.git] / libsecurity_smime / lib / cmscinfo.c
CommitLineData
b1ab9ed8
A
1/*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Netscape security libraries.
13 *
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation. Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation. All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above. If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL. If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
31 * GPL.
32 */
33
34/*
35 * CMS contentInfo methods.
36 */
37
38#include <Security/SecCmsContentInfo.h>
39
40#include <Security/SecCmsDigestContext.h>
41#include <Security/SecCmsDigestedData.h>
42#include <Security/SecCmsEncryptedData.h>
43#include <Security/SecCmsEnvelopedData.h>
44#include <Security/SecCmsSignedData.h>
45
46#include "cmslocal.h"
47
48//#include "pk11func.h"
49#include "secoid.h"
d8f41ccd 50#include "SecAsn1Item.h"
b1ab9ed8
A
51
52#include <security_asn1/secerr.h>
d8f41ccd 53#include <security_asn1/secport.h>
b1ab9ed8 54
d8f41ccd 55#include <Security/SecBase.h>
b1ab9ed8
A
56
57/*
58 * SecCmsContentInfoDestroy - destroy a CMS contentInfo and all of its sub-pieces.
59 */
60void
61SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo)
62{
63 SECOidTag kind;
64
fa7225c8
A
65 if(!cinfo) return;
66
b1ab9ed8
A
67 kind = SecCmsContentInfoGetContentTypeTag(cinfo);
68 switch (kind) {
69 case SEC_OID_PKCS7_ENVELOPED_DATA:
70 SecCmsEnvelopedDataDestroy(cinfo->content.envelopedData);
71 break;
72 case SEC_OID_PKCS7_SIGNED_DATA:
73 SecCmsSignedDataDestroy(cinfo->content.signedData);
74 break;
75 case SEC_OID_PKCS7_ENCRYPTED_DATA:
76 SecCmsEncryptedDataDestroy(cinfo->content.encryptedData);
77 break;
78 case SEC_OID_PKCS7_DIGESTED_DATA:
79 SecCmsDigestedDataDestroy(cinfo->content.digestedData);
80 break;
81 default:
82 /* XXX Anything else that needs to be "manually" freed/destroyed? */
83 break;
84 }
85 if (cinfo->digcx) {
86 /* must destroy digest objects */
87 SecCmsDigestContextCancel(cinfo->digcx);
88 cinfo->digcx = NULL;
89 }
90 if (cinfo->bulkkey)
91 CFRelease(cinfo->bulkkey);
92 /* @@@ private key is only here as a workaround for 3401088. Note this *must* be released after bulkkey */
93 if (cinfo->privkey)
94 CFRelease(cinfo->privkey);
95
96 if (cinfo->ciphcx) {
97 SecCmsCipherContextDestroy(cinfo->ciphcx);
98 cinfo->ciphcx = NULL;
99 }
100
101 /* we live in a pool, so no need to worry about storage */
102}
103
104/*
105 * SecCmsContentInfoGetChildContentInfo - get content's contentInfo (if it exists)
106 */
107SecCmsContentInfoRef
108SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo)
109{
110 void *ptr = NULL;
111 SecCmsContentInfoRef ccinfo = NULL;
112 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(cinfo);
113 switch (tag) {
114 case SEC_OID_PKCS7_SIGNED_DATA:
115 ptr = (void *)cinfo->content.signedData;
116 ccinfo = &(cinfo->content.signedData->contentInfo);
117 break;
118 case SEC_OID_PKCS7_ENVELOPED_DATA:
119 ptr = (void *)cinfo->content.envelopedData;
120 ccinfo = &(cinfo->content.envelopedData->contentInfo);
121 break;
122 case SEC_OID_PKCS7_DIGESTED_DATA:
123 ptr = (void *)cinfo->content.digestedData;
124 ccinfo = &(cinfo->content.digestedData->contentInfo);
125 break;
126 case SEC_OID_PKCS7_ENCRYPTED_DATA:
127 ptr = (void *)cinfo->content.encryptedData;
128 ccinfo = &(cinfo->content.encryptedData->contentInfo);
129 break;
130 case SEC_OID_PKCS7_DATA:
b1ab9ed8
A
131 default:
132 break;
133 }
134 return (ptr ? ccinfo : NULL);
135}
136
137/*
138 * SecCmsContentInfoSetContent - set content type & content
139 */
140OSStatus
d8f41ccd 141SecCmsContentInfoSetContent(SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr)
b1ab9ed8
A
142{
143 OSStatus rv;
144
145 cinfo->contentTypeTag = SECOID_FindOIDByTag(type);
146 if (cinfo->contentTypeTag == NULL)
d8f41ccd 147 return errSecParam;
b1ab9ed8
A
148
149 /* do not copy the oid, just create a reference */
d8f41ccd 150 rv = SECITEM_CopyItem (cinfo->cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid));
b1ab9ed8 151 if (rv != SECSuccess)
d8f41ccd 152 return errSecAllocate;
b1ab9ed8
A
153
154 cinfo->content.pointer = ptr;
155
156 if (type != SEC_OID_PKCS7_DATA) {
157 /* as we always have some inner data,
158 * we need to set it to something, just to fool the encoder enough to work on it
159 * and get us into nss_cms_encoder_notify at that point */
d8f41ccd 160 cinfo->rawContent = SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1);
b1ab9ed8
A
161 if (cinfo->rawContent == NULL) {
162 PORT_SetError(SEC_ERROR_NO_MEMORY);
d8f41ccd 163 return errSecAllocate;
b1ab9ed8
A
164 }
165 }
166
d8f41ccd 167 return errSecSuccess;
b1ab9ed8
A
168}
169
170/*
171 * SecCmsContentInfoSetContentXXXX - typesafe wrappers for SecCmsContentInfoSetContent
172 */
173
174/*
175 * data == NULL -> pass in data via SecCmsEncoderUpdate
176 * data != NULL -> take this data
177 */
178OSStatus
d8f41ccd 179SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef dataRef, Boolean detached)
b1ab9ed8 180{
d8f41ccd
A
181 SecAsn1Item * data = NULL;
182 if (dataRef) {
183 /* @@@ Fixme CFRetain the passed in data rather than
184 always copying it for performance. */
185 data = PORT_ArenaAlloc(cinfo->cmsg->poolp, sizeof(SecAsn1Item));
186 data->Length = CFDataGetLength(dataRef);
187 if (data->Length) {
188 data->Data = PORT_ArenaAlloc(cinfo->cmsg->poolp, data->Length);
189 memcpy(data->Data, CFDataGetBytePtr(dataRef), data->Length);
190 }
191 else
192 data->Data = NULL;
193 }
194
ecaf5866
A
195 if (SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess) {
196 OSStatus status = PORT_GetError();
197 PORT_SetError(0); // clean the thread since we've returned this error
198 return status;
199 }
b1ab9ed8
A
200 cinfo->rawContent = (detached) ?
201 NULL : (data) ?
d8f41ccd
A
202 data : SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1);
203 return errSecSuccess;
b1ab9ed8
A
204}
205
206OSStatus
d8f41ccd 207SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd)
b1ab9ed8 208{
d8f41ccd 209 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd);
b1ab9ed8
A
210}
211
212OSStatus
d8f41ccd 213SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd)
b1ab9ed8 214{
d8f41ccd 215 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd);
b1ab9ed8
A
216}
217
218OSStatus
d8f41ccd 219SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd)
b1ab9ed8 220{
d8f41ccd 221 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd);
b1ab9ed8
A
222}
223
224OSStatus
d8f41ccd 225SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd)
b1ab9ed8 226{
d8f41ccd 227 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
b1ab9ed8
A
228}
229
866f8763
A
230OSStatus
231SecCmsContentInfoSetContentOther(SecCmsContentInfoRef cinfo, SecAsn1Item *data, Boolean detached, const SecAsn1Oid *eContentType)
232{
233 SECStatus srtn;
234 SECOidData *tmpOidData;
235
236 /* just like SecCmsContentInfoSetContentData, except override the contentType and
237 * contentTypeTag. This OID is for encoding... */
238 srtn = SECITEM_CopyItem (cinfo->cmsg->poolp, &(cinfo->contentType), eContentType);
239 if (srtn != SECSuccess) {
240 return errSecAllocate;
241 }
242
243 /* this serves up a contentTypeTag with an empty OID */
244 tmpOidData = SECOID_FindOIDByTag(SEC_OID_OTHER);
245 /* but that's const: cook up a new one we can write to */
246 cinfo->contentTypeTag = (SECOidData *)PORT_ArenaZAlloc(cinfo->cmsg->poolp, sizeof(SECOidData));
247 *cinfo->contentTypeTag = *tmpOidData;
248 /* now fill in the OID */
249 srtn = SECITEM_CopyItem (cinfo->cmsg->poolp, &(cinfo->contentTypeTag->oid), eContentType);
250 if (srtn != SECSuccess) {
251 return errSecAllocate;
252 }
253 cinfo->content.pointer = data;
254 cinfo->rawContent = (detached) ? NULL : (data) ?
255 data : SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1);
256 return noErr;
257}
258
b1ab9ed8
A
259/*
260 * SecCmsContentInfoGetContent - get pointer to inner content
261 *
262 * needs to be casted...
263 */
264void *
265SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo)
266{
267 SECOidTag tag = (cinfo && cinfo->contentTypeTag)
268 ? cinfo->contentTypeTag->offset
d8f41ccd 269 : SEC_OID_UNKNOWN;
b1ab9ed8
A
270 switch (tag) {
271 case SEC_OID_PKCS7_DATA:
272 case SEC_OID_PKCS7_SIGNED_DATA:
273 case SEC_OID_PKCS7_ENVELOPED_DATA:
274 case SEC_OID_PKCS7_DIGESTED_DATA:
275 case SEC_OID_PKCS7_ENCRYPTED_DATA:
b1ab9ed8
A
276 return cinfo->content.pointer;
277 default:
278 return NULL;
279 }
280}
281
282/*
283 * SecCmsContentInfoGetInnerContent - get pointer to innermost content
284 *
285 * this is typically only called by SecCmsMessageGetContent()
286 */
d8f41ccd 287const SecAsn1Item *
b1ab9ed8
A
288SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo)
289{
d8f41ccd 290 SecCmsContentInfoRef ccinfo;
b1ab9ed8 291 SECOidTag tag;
d8f41ccd 292 SecAsn1Item * pItem;
b1ab9ed8 293
d8f41ccd
A
294 tag = SecCmsContentInfoGetContentTypeTag(cinfo);
295 switch (tag) {
296 case SEC_OID_PKCS7_DATA:
297 /* end of recursion - every message has to have a data cinfo */
298 pItem = cinfo->content.data;
299 break;
300 case SEC_OID_PKCS7_DIGESTED_DATA:
301 case SEC_OID_PKCS7_ENCRYPTED_DATA:
302 case SEC_OID_PKCS7_ENVELOPED_DATA:
303 case SEC_OID_PKCS7_SIGNED_DATA:
304 ccinfo = SecCmsContentInfoGetChildContentInfo(cinfo);
305 if (ccinfo == NULL)
306 pItem = NULL;
307 else
308 pItem = SecCmsContentInfoGetContent(ccinfo);
309 break;
310 default:
311 PORT_Assert(0);
312 pItem = NULL;
313 break;
b1ab9ed8 314 }
d8f41ccd 315 return pItem;
b1ab9ed8
A
316}
317
318/*
319 * SecCmsContentInfoGetContentType{Tag,OID} - find out (saving pointer to lookup result
320 * for future reference) and return the inner content type.
321 */
322SECOidTag
323SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo)
324{
325 if (cinfo->contentTypeTag == NULL)
326 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
327
328 if (cinfo->contentTypeTag == NULL)
d8f41ccd 329 return SEC_OID_UNKNOWN;
b1ab9ed8
A
330
331 return cinfo->contentTypeTag->offset;
332}
333
d8f41ccd 334SecAsn1Oid *
b1ab9ed8
A
335SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo)
336{
337 if (cinfo->contentTypeTag == NULL)
338 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
339
d8f41ccd
A
340 if (cinfo->contentTypeTag == NULL)
341 return NULL;
342
b1ab9ed8
A
343 return &(cinfo->contentTypeTag->oid);
344}
345
346/*
347 * SecCmsContentInfoGetContentEncAlgTag - find out (saving pointer to lookup result
348 * for future reference) and return the content encryption algorithm tag.
349 */
350SECOidTag
351SecCmsContentInfoGetContentEncAlgTag(SecCmsContentInfoRef cinfo)
352{
353 if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN)
354 cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg));
355
356 return cinfo->contentEncAlgTag;
357}
358
359/*
360 * SecCmsContentInfoGetContentEncAlg - find out and return the content encryption algorithm tag.
361 */
362SECAlgorithmID *
363SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo)
364{
365 return &(cinfo->contentEncAlg);
366}
367
368OSStatus
d8f41ccd
A
369SecCmsContentInfoSetContentEncAlg(SecCmsContentInfoRef cinfo,
370 SECOidTag bulkalgtag, const SecAsn1Item *parameters, int keysize)
b1ab9ed8 371{
d8f41ccd 372 PLArenaPool *poolp = cinfo->cmsg->poolp;
b1ab9ed8
A
373 OSStatus rv;
374
375 rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters);
376 if (rv != SECSuccess)
377 return SECFailure;
378 cinfo->keysize = keysize;
379 return SECSuccess;
380}
381
382OSStatus
d8f41ccd 383SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo,
b1ab9ed8
A
384 SECAlgorithmID *algid, int keysize)
385{
d8f41ccd 386 PLArenaPool *poolp = cinfo->cmsg->poolp;
b1ab9ed8
A
387 OSStatus rv;
388
389 rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid);
390 if (rv != SECSuccess)
391 return SECFailure;
392 if (keysize >= 0)
393 cinfo->keysize = keysize;
394 return SECSuccess;
395}
396
397void
398SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey)
399{
866f8763
A
400#ifdef USE_CDSA_CRYPTO
401 const CSSM_KEY *cssmKey = NULL;
402#endif
fa7225c8 403 if (!bulkkey || !cinfo) return;
b1ab9ed8
A
404 cinfo->bulkkey = bulkkey;
405 CFRetain(cinfo->bulkkey);
866f8763
A
406#ifdef USE_CDSA_CRYPTO
407 SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey);
408 cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0;
409#else
fa7225c8
A
410 long long bulkKeySize = CFDataGetLength((CFDataRef)bulkkey) * 8;
411 if (bulkKeySize < INT_MAX) {
412 cinfo->keysize = (int)bulkKeySize;
413 } else {
414 CFRelease(cinfo->bulkkey);
415 cinfo->bulkkey = NULL;
416 cinfo->keysize = 0;
417 }
866f8763 418#endif
b1ab9ed8
A
419}
420
421SecSymmetricKeyRef
422SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo)
423{
424 if (cinfo->bulkkey == NULL)
425 return NULL;
426
427 CFRetain(cinfo->bulkkey);
428 return cinfo->bulkkey;
429}
430
431int
432SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo)
433{
434 return cinfo->keysize;
435}