]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/cmscinfo.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / cmscinfo.c
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"
50 #include "secitem.h"
51
52 #include <security_asn1/secerr.h>
53 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
54
55 /*
56 * SecCmsContentInfoCreate - create a content info
57 *
58 * version is set in the _Finalize procedures for each content type
59 */
60
61 /*
62 * SecCmsContentInfoDestroy - destroy a CMS contentInfo and all of its sub-pieces.
63 */
64 void
65 SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo)
66 {
67 SECOidTag kind;
68
69 if(!cinfo) return;
70
71 kind = SecCmsContentInfoGetContentTypeTag(cinfo);
72 switch (kind) {
73 case SEC_OID_PKCS7_ENVELOPED_DATA:
74 SecCmsEnvelopedDataDestroy(cinfo->content.envelopedData);
75 break;
76 case SEC_OID_PKCS7_SIGNED_DATA:
77 SecCmsSignedDataDestroy(cinfo->content.signedData);
78 break;
79 case SEC_OID_PKCS7_ENCRYPTED_DATA:
80 SecCmsEncryptedDataDestroy(cinfo->content.encryptedData);
81 break;
82 case SEC_OID_PKCS7_DIGESTED_DATA:
83 SecCmsDigestedDataDestroy(cinfo->content.digestedData);
84 break;
85 default:
86 /* XXX Anything else that needs to be "manually" freed/destroyed? */
87 break;
88 }
89 if (cinfo->digcx) {
90 /* must destroy digest objects */
91 SecCmsDigestContextCancel(cinfo->digcx);
92 cinfo->digcx = NULL;
93 }
94 if (cinfo->bulkkey)
95 CFRelease(cinfo->bulkkey);
96 /* @@@ private key is only here as a workaround for 3401088. Note this *must* be released after bulkkey */
97 if (cinfo->privkey)
98 CFRelease(cinfo->privkey);
99
100 if (cinfo->ciphcx) {
101 SecCmsCipherContextDestroy(cinfo->ciphcx);
102 cinfo->ciphcx = NULL;
103 }
104
105 /* we live in a pool, so no need to worry about storage */
106 }
107
108 /*
109 * SecCmsContentInfoGetChildContentInfo - get content's contentInfo (if it exists)
110 */
111 SecCmsContentInfoRef
112 SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo)
113 {
114 void *ptr = NULL;
115 SecCmsContentInfoRef ccinfo = NULL;
116 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(cinfo);
117 switch (tag) {
118 case SEC_OID_PKCS7_SIGNED_DATA:
119 ptr = (void *)cinfo->content.signedData;
120 ccinfo = &(cinfo->content.signedData->contentInfo);
121 break;
122 case SEC_OID_PKCS7_ENVELOPED_DATA:
123 ptr = (void *)cinfo->content.envelopedData;
124 ccinfo = &(cinfo->content.envelopedData->contentInfo);
125 break;
126 case SEC_OID_PKCS7_DIGESTED_DATA:
127 ptr = (void *)cinfo->content.digestedData;
128 ccinfo = &(cinfo->content.digestedData->contentInfo);
129 break;
130 case SEC_OID_PKCS7_ENCRYPTED_DATA:
131 ptr = (void *)cinfo->content.encryptedData;
132 ccinfo = &(cinfo->content.encryptedData->contentInfo);
133 break;
134 case SEC_OID_PKCS7_DATA:
135 case SEC_OID_OTHER:
136 default:
137 break;
138 }
139 return (ptr ? ccinfo : NULL);
140 }
141
142 /*
143 * SecCmsContentInfoSetContent - set content type & content
144 */
145 OSStatus
146 SecCmsContentInfoSetContent(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr)
147 {
148 OSStatus rv;
149
150 cinfo->contentTypeTag = SECOID_FindOIDByTag(type);
151 if (cinfo->contentTypeTag == NULL)
152 return paramErr;
153
154 /* do not copy the oid, just create a reference */
155 rv = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid));
156 if (rv != SECSuccess)
157 return memFullErr;
158
159 cinfo->content.pointer = ptr;
160
161 if (type != SEC_OID_PKCS7_DATA) {
162 /* as we always have some inner data,
163 * we need to set it to something, just to fool the encoder enough to work on it
164 * and get us into nss_cms_encoder_notify at that point */
165 cinfo->rawContent = SECITEM_AllocItem(cmsg->poolp, NULL, 1);
166 if (cinfo->rawContent == NULL) {
167 PORT_SetError(SEC_ERROR_NO_MEMORY);
168 return memFullErr;
169 }
170 }
171
172 return noErr;
173 }
174
175 /*
176 * SecCmsContentInfoSetContentXXXX - typesafe wrappers for SecCmsContentInfoSetContent
177 */
178
179 /*
180 * data == NULL -> pass in data via SecCmsEncoderUpdate
181 * data != NULL -> take this data
182 */
183 OSStatus
184 SecCmsContentInfoSetContentData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached)
185 {
186 if (SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess)
187 return PORT_GetError();
188 cinfo->rawContent = (detached) ?
189 NULL : (data) ?
190 data : SECITEM_AllocItem(cmsg->poolp, NULL, 1);
191 return noErr;
192 }
193
194 OSStatus
195 SecCmsContentInfoSetContentSignedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd)
196 {
197 return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd);
198 }
199
200 OSStatus
201 SecCmsContentInfoSetContentEnvelopedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd)
202 {
203 return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd);
204 }
205
206 OSStatus
207 SecCmsContentInfoSetContentDigestedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd)
208 {
209 return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd);
210 }
211
212 OSStatus
213 SecCmsContentInfoSetContentEncryptedData(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd)
214 {
215 return SecCmsContentInfoSetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
216 }
217
218 OSStatus
219 SecCmsContentInfoSetContentOther(SecCmsMessageRef cmsg, SecCmsContentInfoRef cinfo, CSSM_DATA_PTR data, Boolean detached, const CSSM_OID *eContentType)
220 {
221 SECStatus srtn;
222 SECOidData *tmpOidData;
223
224 /* just like SecCmsContentInfoSetContentData, except override the contentType and
225 * contentTypeTag. This OID is for encoding... */
226 srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentType), eContentType);
227 if (srtn != SECSuccess) {
228 return memFullErr;
229 }
230
231 /* this serves up a contentTypeTag with an empty OID */
232 tmpOidData = SECOID_FindOIDByTag(SEC_OID_OTHER);
233 /* but that's const: cook up a new one we can write to */
234 cinfo->contentTypeTag = (SECOidData *)PORT_ArenaZAlloc(cmsg->poolp, sizeof(SECOidData));
235 *cinfo->contentTypeTag = *tmpOidData;
236 /* now fill in the OID */
237 srtn = SECITEM_CopyItem (cmsg->poolp, &(cinfo->contentTypeTag->oid), eContentType);
238 if (srtn != SECSuccess) {
239 return memFullErr;
240 }
241 cinfo->content.pointer = data;
242 cinfo->rawContent = (detached) ?
243 NULL : (data) ?
244 data : SECITEM_AllocItem(cmsg->poolp, NULL, 1);
245 return noErr;
246 }
247
248
249 /*
250 * SecCmsContentInfoGetContent - get pointer to inner content
251 *
252 * needs to be casted...
253 */
254 void *
255 SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo)
256 {
257 if (!cinfo) { return NULL; }
258 SECOidTag tag = (cinfo->contentTypeTag) ? cinfo->contentTypeTag->offset
259 : ( cinfo->contentType.Data ? SEC_OID_OTHER : SEC_OID_UNKNOWN);
260 switch (tag) {
261 case SEC_OID_PKCS7_DATA:
262 case SEC_OID_PKCS7_SIGNED_DATA:
263 case SEC_OID_PKCS7_ENVELOPED_DATA:
264 case SEC_OID_PKCS7_DIGESTED_DATA:
265 case SEC_OID_PKCS7_ENCRYPTED_DATA:
266 case SEC_OID_OTHER:
267 return cinfo->content.pointer;
268 default:
269 return NULL;
270 }
271 }
272
273 /*
274 * SecCmsContentInfoGetInnerContent - get pointer to innermost content
275 *
276 * this is typically only called by SecCmsMessageGetContent()
277 */
278 CSSM_DATA_PTR
279 SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo)
280 {
281 SECOidTag tag;
282
283 for(;;) {
284 tag = SecCmsContentInfoGetContentTypeTag(cinfo);
285 switch (tag) {
286 case SEC_OID_PKCS7_DATA:
287 case SEC_OID_OTHER:
288 /* end of recursion - every message has to have a data cinfo */
289 return cinfo->content.data;
290 case SEC_OID_PKCS7_DIGESTED_DATA:
291 case SEC_OID_PKCS7_ENCRYPTED_DATA:
292 case SEC_OID_PKCS7_ENVELOPED_DATA:
293 case SEC_OID_PKCS7_SIGNED_DATA:
294 cinfo = SecCmsContentInfoGetChildContentInfo(cinfo);
295 if (cinfo == NULL) {
296 return NULL;
297 }
298 /* else recurse */
299 break;
300 case SEC_OID_PKCS9_ID_CT_TSTInfo:
301 /* end of recursion - every message has to have a data cinfo */
302 return cinfo->rawContent;
303 default:
304 PORT_Assert(0);
305 return NULL;
306 }
307 }
308 /* NOT REACHED */
309 return NULL;
310 }
311
312 /*
313 * SecCmsContentInfoGetContentType{Tag,OID} - find out (saving pointer to lookup result
314 * for future reference) and return the inner content type.
315 */
316 SECOidTag
317 SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo)
318 {
319 if (cinfo->contentTypeTag == NULL)
320 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
321
322 if (cinfo->contentTypeTag == NULL)
323 return SEC_OID_OTHER; // was...SEC_OID_UNKNOWN OK?
324
325 return cinfo->contentTypeTag->offset;
326 }
327
328 CSSM_DATA_PTR
329 SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo)
330 {
331 if (cinfo->contentTypeTag == NULL)
332 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
333
334 if (cinfo->contentTypeTag == NULL) {
335 /* if we have an OID but we just don't recognize it, return that */
336 if(cinfo->contentType.Data != NULL) {
337 return &cinfo->contentType;
338 }
339 else {
340 return NULL;
341 }
342 }
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 */
350 SECOidTag
351 SecCmsContentInfoGetContentEncAlgTag(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 */
362 SECAlgorithmID *
363 SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo)
364 {
365 return &(cinfo->contentEncAlg);
366 }
367
368 OSStatus
369 SecCmsContentInfoSetContentEncAlg(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo,
370 SECOidTag bulkalgtag, CSSM_DATA_PTR parameters, int keysize)
371 {
372 PLArenaPool *poolp = (PLArenaPool *)pool;
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
382 OSStatus
383 SecCmsContentInfoSetContentEncAlgID(SecArenaPoolRef pool, SecCmsContentInfoRef cinfo,
384 SECAlgorithmID *algid, int keysize)
385 {
386 PLArenaPool *poolp = (PLArenaPool *)pool;
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
397 void
398 SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey)
399 {
400 const CSSM_KEY *cssmKey = NULL;
401
402 cinfo->bulkkey = bulkkey;
403 CFRetain(cinfo->bulkkey);
404 SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey);
405 cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0;
406 }
407
408 SecSymmetricKeyRef
409 SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo)
410 {
411 if (cinfo->bulkkey == NULL)
412 return NULL;
413
414 CFRetain(cinfo->bulkkey);
415 return cinfo->bulkkey;
416 }
417
418 int
419 SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo)
420 {
421 return cinfo->keysize;
422 }