]> git.saurik.com Git - apple/security.git/blob - libsecurity_smime/security_smime/cmscinfo.c
Security-57336.1.9.tar.gz
[apple/security.git] / libsecurity_smime / security_smime / 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 "SecAsn1Item.h"
51
52 #include <security_asn1/secerr.h>
53 #include <security_asn1/secport.h>
54
55 #include <Security/SecBase.h>
56
57 /*
58 * SecCmsContentInfoDestroy - destroy a CMS contentInfo and all of its sub-pieces.
59 */
60 void
61 SecCmsContentInfoDestroy(SecCmsContentInfoRef cinfo)
62 {
63 SECOidTag kind;
64
65 kind = SecCmsContentInfoGetContentTypeTag(cinfo);
66 switch (kind) {
67 case SEC_OID_PKCS7_ENVELOPED_DATA:
68 SecCmsEnvelopedDataDestroy(cinfo->content.envelopedData);
69 break;
70 case SEC_OID_PKCS7_SIGNED_DATA:
71 SecCmsSignedDataDestroy(cinfo->content.signedData);
72 break;
73 case SEC_OID_PKCS7_ENCRYPTED_DATA:
74 SecCmsEncryptedDataDestroy(cinfo->content.encryptedData);
75 break;
76 case SEC_OID_PKCS7_DIGESTED_DATA:
77 SecCmsDigestedDataDestroy(cinfo->content.digestedData);
78 break;
79 default:
80 /* XXX Anything else that needs to be "manually" freed/destroyed? */
81 break;
82 }
83 if (cinfo->digcx) {
84 /* must destroy digest objects */
85 SecCmsDigestContextCancel(cinfo->digcx);
86 cinfo->digcx = NULL;
87 }
88 if (cinfo->bulkkey)
89 CFRelease(cinfo->bulkkey);
90 /* @@@ private key is only here as a workaround for 3401088. Note this *must* be released after bulkkey */
91 if (cinfo->privkey)
92 CFRelease(cinfo->privkey);
93
94 if (cinfo->ciphcx) {
95 SecCmsCipherContextDestroy(cinfo->ciphcx);
96 cinfo->ciphcx = NULL;
97 }
98
99 /* we live in a pool, so no need to worry about storage */
100 }
101
102 /*
103 * SecCmsContentInfoGetChildContentInfo - get content's contentInfo (if it exists)
104 */
105 SecCmsContentInfoRef
106 SecCmsContentInfoGetChildContentInfo(SecCmsContentInfoRef cinfo)
107 {
108 void *ptr = NULL;
109 SecCmsContentInfoRef ccinfo = NULL;
110 SECOidTag tag = SecCmsContentInfoGetContentTypeTag(cinfo);
111 switch (tag) {
112 case SEC_OID_PKCS7_SIGNED_DATA:
113 ptr = (void *)cinfo->content.signedData;
114 ccinfo = &(cinfo->content.signedData->contentInfo);
115 break;
116 case SEC_OID_PKCS7_ENVELOPED_DATA:
117 ptr = (void *)cinfo->content.envelopedData;
118 ccinfo = &(cinfo->content.envelopedData->contentInfo);
119 break;
120 case SEC_OID_PKCS7_DIGESTED_DATA:
121 ptr = (void *)cinfo->content.digestedData;
122 ccinfo = &(cinfo->content.digestedData->contentInfo);
123 break;
124 case SEC_OID_PKCS7_ENCRYPTED_DATA:
125 ptr = (void *)cinfo->content.encryptedData;
126 ccinfo = &(cinfo->content.encryptedData->contentInfo);
127 break;
128 case SEC_OID_PKCS7_DATA:
129 default:
130 break;
131 }
132 return (ptr ? ccinfo : NULL);
133 }
134
135 /*
136 * SecCmsContentInfoSetContent - set content type & content
137 */
138 OSStatus
139 SecCmsContentInfoSetContent(SecCmsContentInfoRef cinfo, SECOidTag type, void *ptr)
140 {
141 OSStatus rv;
142
143 cinfo->contentTypeTag = SECOID_FindOIDByTag(type);
144 if (cinfo->contentTypeTag == NULL)
145 return errSecParam;
146
147 /* do not copy the oid, just create a reference */
148 rv = SECITEM_CopyItem (cinfo->cmsg->poolp, &(cinfo->contentType), &(cinfo->contentTypeTag->oid));
149 if (rv != SECSuccess)
150 return errSecAllocate;
151
152 cinfo->content.pointer = ptr;
153
154 if (type != SEC_OID_PKCS7_DATA) {
155 /* as we always have some inner data,
156 * we need to set it to something, just to fool the encoder enough to work on it
157 * and get us into nss_cms_encoder_notify at that point */
158 cinfo->rawContent = SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1);
159 if (cinfo->rawContent == NULL) {
160 PORT_SetError(SEC_ERROR_NO_MEMORY);
161 return errSecAllocate;
162 }
163 }
164
165 return errSecSuccess;
166 }
167
168 /*
169 * SecCmsContentInfoSetContentXXXX - typesafe wrappers for SecCmsContentInfoSetContent
170 */
171
172 /*
173 * data == NULL -> pass in data via SecCmsEncoderUpdate
174 * data != NULL -> take this data
175 */
176 OSStatus
177 SecCmsContentInfoSetContentData(SecCmsContentInfoRef cinfo, CFDataRef dataRef, Boolean detached)
178 {
179 SecAsn1Item * data = NULL;
180 if (dataRef) {
181 /* @@@ Fixme CFRetain the passed in data rather than
182 always copying it for performance. */
183 data = PORT_ArenaAlloc(cinfo->cmsg->poolp, sizeof(SecAsn1Item));
184 data->Length = CFDataGetLength(dataRef);
185 if (data->Length) {
186 data->Data = PORT_ArenaAlloc(cinfo->cmsg->poolp, data->Length);
187 memcpy(data->Data, CFDataGetBytePtr(dataRef), data->Length);
188 }
189 else
190 data->Data = NULL;
191 }
192
193 if (SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess)
194 return PORT_GetError();
195 cinfo->rawContent = (detached) ?
196 NULL : (data) ?
197 data : SECITEM_AllocItem(cinfo->cmsg->poolp, NULL, 1);
198 return errSecSuccess;
199 }
200
201 OSStatus
202 SecCmsContentInfoSetContentSignedData(SecCmsContentInfoRef cinfo, SecCmsSignedDataRef sigd)
203 {
204 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_SIGNED_DATA, (void *)sigd);
205 }
206
207 OSStatus
208 SecCmsContentInfoSetContentEnvelopedData(SecCmsContentInfoRef cinfo, SecCmsEnvelopedDataRef envd)
209 {
210 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_ENVELOPED_DATA, (void *)envd);
211 }
212
213 OSStatus
214 SecCmsContentInfoSetContentDigestedData(SecCmsContentInfoRef cinfo, SecCmsDigestedDataRef digd)
215 {
216 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_DIGESTED_DATA, (void *)digd);
217 }
218
219 OSStatus
220 SecCmsContentInfoSetContentEncryptedData(SecCmsContentInfoRef cinfo, SecCmsEncryptedDataRef encd)
221 {
222 return SecCmsContentInfoSetContent(cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
223 }
224
225 /*
226 * SecCmsContentInfoGetContent - get pointer to inner content
227 *
228 * needs to be casted...
229 */
230 void *
231 SecCmsContentInfoGetContent(SecCmsContentInfoRef cinfo)
232 {
233 SECOidTag tag = (cinfo && cinfo->contentTypeTag)
234 ? cinfo->contentTypeTag->offset
235 : SEC_OID_UNKNOWN;
236 switch (tag) {
237 case SEC_OID_PKCS7_DATA:
238 case SEC_OID_PKCS7_SIGNED_DATA:
239 case SEC_OID_PKCS7_ENVELOPED_DATA:
240 case SEC_OID_PKCS7_DIGESTED_DATA:
241 case SEC_OID_PKCS7_ENCRYPTED_DATA:
242 return cinfo->content.pointer;
243 default:
244 return NULL;
245 }
246 }
247
248 /*
249 * SecCmsContentInfoGetInnerContent - get pointer to innermost content
250 *
251 * this is typically only called by SecCmsMessageGetContent()
252 */
253 const SecAsn1Item *
254 SecCmsContentInfoGetInnerContent(SecCmsContentInfoRef cinfo)
255 {
256 SecCmsContentInfoRef ccinfo;
257 SECOidTag tag;
258 SecAsn1Item * pItem;
259
260 tag = SecCmsContentInfoGetContentTypeTag(cinfo);
261 switch (tag) {
262 case SEC_OID_PKCS7_DATA:
263 /* end of recursion - every message has to have a data cinfo */
264 pItem = cinfo->content.data;
265 break;
266 case SEC_OID_PKCS7_DIGESTED_DATA:
267 case SEC_OID_PKCS7_ENCRYPTED_DATA:
268 case SEC_OID_PKCS7_ENVELOPED_DATA:
269 case SEC_OID_PKCS7_SIGNED_DATA:
270 ccinfo = SecCmsContentInfoGetChildContentInfo(cinfo);
271 if (ccinfo == NULL)
272 pItem = NULL;
273 else
274 pItem = SecCmsContentInfoGetContent(ccinfo);
275 break;
276 default:
277 PORT_Assert(0);
278 pItem = NULL;
279 break;
280 }
281 return pItem;
282 }
283
284 /*
285 * SecCmsContentInfoGetContentType{Tag,OID} - find out (saving pointer to lookup result
286 * for future reference) and return the inner content type.
287 */
288 SECOidTag
289 SecCmsContentInfoGetContentTypeTag(SecCmsContentInfoRef cinfo)
290 {
291 if (cinfo->contentTypeTag == NULL)
292 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
293
294 if (cinfo->contentTypeTag == NULL)
295 return SEC_OID_UNKNOWN;
296
297 return cinfo->contentTypeTag->offset;
298 }
299
300 SecAsn1Oid *
301 SecCmsContentInfoGetContentTypeOID(SecCmsContentInfoRef cinfo)
302 {
303 if (cinfo->contentTypeTag == NULL)
304 cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType));
305
306 if (cinfo->contentTypeTag == NULL)
307 return NULL;
308
309 return &(cinfo->contentTypeTag->oid);
310 }
311
312 /*
313 * SecCmsContentInfoGetContentEncAlgTag - find out (saving pointer to lookup result
314 * for future reference) and return the content encryption algorithm tag.
315 */
316 SECOidTag
317 SecCmsContentInfoGetContentEncAlgTag(SecCmsContentInfoRef cinfo)
318 {
319 if (cinfo->contentEncAlgTag == SEC_OID_UNKNOWN)
320 cinfo->contentEncAlgTag = SECOID_GetAlgorithmTag(&(cinfo->contentEncAlg));
321
322 return cinfo->contentEncAlgTag;
323 }
324
325 /*
326 * SecCmsContentInfoGetContentEncAlg - find out and return the content encryption algorithm tag.
327 */
328 SECAlgorithmID *
329 SecCmsContentInfoGetContentEncAlg(SecCmsContentInfoRef cinfo)
330 {
331 return &(cinfo->contentEncAlg);
332 }
333
334 OSStatus
335 SecCmsContentInfoSetContentEncAlg(SecCmsContentInfoRef cinfo,
336 SECOidTag bulkalgtag, const SecAsn1Item *parameters, int keysize)
337 {
338 PLArenaPool *poolp = cinfo->cmsg->poolp;
339 OSStatus rv;
340
341 rv = SECOID_SetAlgorithmID(poolp, &(cinfo->contentEncAlg), bulkalgtag, parameters);
342 if (rv != SECSuccess)
343 return SECFailure;
344 cinfo->keysize = keysize;
345 return SECSuccess;
346 }
347
348 OSStatus
349 SecCmsContentInfoSetContentEncAlgID(SecCmsContentInfoRef cinfo,
350 SECAlgorithmID *algid, int keysize)
351 {
352 PLArenaPool *poolp = cinfo->cmsg->poolp;
353 OSStatus rv;
354
355 rv = SECOID_CopyAlgorithmID(poolp, &(cinfo->contentEncAlg), algid);
356 if (rv != SECSuccess)
357 return SECFailure;
358 if (keysize >= 0)
359 cinfo->keysize = keysize;
360 return SECSuccess;
361 }
362
363 void
364 SecCmsContentInfoSetBulkKey(SecCmsContentInfoRef cinfo, SecSymmetricKeyRef bulkkey)
365 {
366 #ifdef USE_CDSA_CRYPTO
367 const CSSM_KEY *cssmKey = NULL;
368 #endif
369 cinfo->bulkkey = bulkkey;
370 CFRetain(cinfo->bulkkey);
371 #ifdef USE_CDSA_CRYPTO
372 SecKeyGetCSSMKey(cinfo->bulkkey, &cssmKey);
373 cinfo->keysize = cssmKey ? cssmKey->KeyHeader.LogicalKeySizeInBits : 0;
374 #else
375 /* This cast should be always safe, there should be SecSymmetricKeyRef API to get the size anyway */
376 cinfo->keysize = (int)CFDataGetLength((CFDataRef)bulkkey) * 8;
377 #endif
378 }
379
380 SecSymmetricKeyRef
381 SecCmsContentInfoGetBulkKey(SecCmsContentInfoRef cinfo)
382 {
383 if (cinfo->bulkkey == NULL)
384 return NULL;
385
386 CFRetain(cinfo->bulkkey);
387 return cinfo->bulkkey;
388 }
389
390 int
391 SecCmsContentInfoGetBulkKeySize(SecCmsContentInfoRef cinfo)
392 {
393 return cinfo->keysize;
394 }