]> git.saurik.com Git - apple/security.git/blame - libsecurity_smime/lib/cmsencdata.c
Security-57740.31.2.tar.gz
[apple/security.git] / libsecurity_smime / lib / cmsencdata.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 encryptedData methods.
36 */
37
38#include <Security/SecCmsEncryptedData.h>
39
40#include <Security/SecCmsContentInfo.h>
41
42#include "cmslocal.h"
43
d8f41ccd 44#include "SecAsn1Item.h"
b1ab9ed8 45#include "secoid.h"
d8f41ccd 46
b1ab9ed8
A
47#include <security_asn1/secasn1.h>
48#include <security_asn1/secerr.h>
d8f41ccd 49#include <security_asn1/secport.h>
b1ab9ed8
A
50
51/*
52 * SecCmsEncryptedDataCreate - create an empty encryptedData object.
53 *
54 * "algorithm" specifies the bulk encryption algorithm to use.
55 * "keysize" is the key size.
56 *
57 * An error results in a return value of NULL and an error set.
58 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
59 */
60SecCmsEncryptedDataRef
61SecCmsEncryptedDataCreate(SecCmsMessageRef cmsg, SECOidTag algorithm, int keysize)
62{
63 void *mark;
64 SecCmsEncryptedDataRef encd;
65 PLArenaPool *poolp;
66 SECAlgorithmID *pbe_algid;
67 OSStatus rv;
68
69 poolp = cmsg->poolp;
70
71 mark = PORT_ArenaMark(poolp);
72
73 encd = (SecCmsEncryptedDataRef)PORT_ArenaZAlloc(poolp, sizeof(SecCmsEncryptedData));
74 if (encd == NULL)
75 goto loser;
76
d8f41ccd 77 encd->contentInfo.cmsg = cmsg;
b1ab9ed8
A
78
79 /* version is set in SecCmsEncryptedDataEncodeBeforeStart() */
80
81 switch (algorithm) {
82 /* XXX hmmm... hardcoded algorithms? */
d8f41ccd
A
83 case SEC_OID_AES_128_CBC:
84 case SEC_OID_AES_192_CBC:
85 case SEC_OID_AES_256_CBC:
b1ab9ed8
A
86 case SEC_OID_RC2_CBC:
87 case SEC_OID_DES_EDE3_CBC:
88 case SEC_OID_DES_CBC:
d8f41ccd 89 rv = SecCmsContentInfoSetContentEncAlg(&(encd->contentInfo), algorithm, NULL, keysize);
b1ab9ed8
A
90 break;
91 default:
92 /* Assume password-based-encryption. At least, try that. */
93#if 1
94 // @@@ Fix me
95 pbe_algid = NULL;
96#else
97 pbe_algid = PK11_CreatePBEAlgorithmID(algorithm, 1, NULL);
98#endif
99 if (pbe_algid == NULL) {
100 rv = SECFailure;
101 break;
102 }
d8f41ccd 103 rv = SecCmsContentInfoSetContentEncAlgID(&(encd->contentInfo), pbe_algid, keysize);
b1ab9ed8
A
104 SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE);
105 break;
106 }
107 if (rv != SECSuccess)
108 goto loser;
109
110 PORT_ArenaUnmark(poolp, mark);
111 return encd;
112
113loser:
114 PORT_ArenaRelease(poolp, mark);
115 return NULL;
116}
117
118/*
119 * SecCmsEncryptedDataDestroy - destroy an encryptedData object
120 */
121void
122SecCmsEncryptedDataDestroy(SecCmsEncryptedDataRef encd)
123{
fa7225c8
A
124 if (encd == NULL) {
125 return;
126 }
b1ab9ed8
A
127 /* everything's in a pool, so don't worry about the storage */
128 SecCmsContentInfoDestroy(&(encd->contentInfo));
129 return;
130}
131
132/*
133 * SecCmsEncryptedDataGetContentInfo - return pointer to encryptedData object's contentInfo
134 */
135SecCmsContentInfoRef
136SecCmsEncryptedDataGetContentInfo(SecCmsEncryptedDataRef encd)
137{
138 return &(encd->contentInfo);
139}
140
141/*
142 * SecCmsEncryptedDataEncodeBeforeStart - do all the necessary things to a EncryptedData
143 * before encoding begins.
144 *
145 * In particular:
146 * - set the correct version value.
147 * - get the encryption key
148 */
149OSStatus
150SecCmsEncryptedDataEncodeBeforeStart(SecCmsEncryptedDataRef encd)
151{
152 int version;
153 SecSymmetricKeyRef bulkkey = NULL;
d8f41ccd 154 SecAsn1Item * dummy;
b1ab9ed8
A
155 SecCmsContentInfoRef cinfo = &(encd->contentInfo);
156
157 if (SecCmsArrayIsEmpty((void **)encd->unprotectedAttr))
158 version = SEC_CMS_ENCRYPTED_DATA_VERSION;
159 else
160 version = SEC_CMS_ENCRYPTED_DATA_VERSION_UPATTR;
161
d8f41ccd 162 dummy = SEC_ASN1EncodeInteger (encd->contentInfo.cmsg->poolp, &(encd->version), version);
b1ab9ed8
A
163 if (dummy == NULL)
164 return SECFailure;
165
166 /* now get content encryption key (bulk key) by using our cmsg callback */
d8f41ccd
A
167 if (encd->contentInfo.cmsg->decrypt_key_cb)
168 bulkkey = (*encd->contentInfo.cmsg->decrypt_key_cb)(encd->contentInfo.cmsg->decrypt_key_cb_arg,
b1ab9ed8
A
169 SecCmsContentInfoGetContentEncAlg(cinfo));
170 if (bulkkey == NULL)
171 return SECFailure;
172
173 /* store the bulk key in the contentInfo so that the encoder can find it */
174 SecCmsContentInfoSetBulkKey(cinfo, bulkkey);
175 CFRelease(bulkkey); /* This assumes the decrypt_key_cb hands us a copy of the key --mb */
176
177 return SECSuccess;
178}
179
180/*
181 * SecCmsEncryptedDataEncodeBeforeData - set up encryption
182 */
183OSStatus
184SecCmsEncryptedDataEncodeBeforeData(SecCmsEncryptedDataRef encd)
185{
186 SecCmsContentInfoRef cinfo;
187 SecSymmetricKeyRef bulkkey;
188 SECAlgorithmID *algid;
189
190 cinfo = &(encd->contentInfo);
191
192 /* find bulkkey and algorithm - must have been set by SecCmsEncryptedDataEncodeBeforeStart */
193 bulkkey = SecCmsContentInfoGetBulkKey(cinfo);
194 if (bulkkey == NULL)
195 return SECFailure;
196 algid = SecCmsContentInfoGetContentEncAlg(cinfo);
197 if (algid == NULL)
198 return SECFailure;
199
200 /* this may modify algid (with IVs generated in a token).
201 * it is therefore essential that algid is a pointer to the "real" contentEncAlg,
202 * not just to a copy */
d8f41ccd 203 cinfo->ciphcx = SecCmsCipherContextStartEncrypt(encd->contentInfo.cmsg->poolp, bulkkey, algid);
b1ab9ed8
A
204 CFRelease(bulkkey);
205 if (cinfo->ciphcx == NULL)
206 return SECFailure;
207
208 return SECSuccess;
209}
210
211/*
212 * SecCmsEncryptedDataEncodeAfterData - finalize this encryptedData for encoding
213 */
214OSStatus
215SecCmsEncryptedDataEncodeAfterData(SecCmsEncryptedDataRef encd)
216{
217 if (encd->contentInfo.ciphcx) {
218 SecCmsCipherContextDestroy(encd->contentInfo.ciphcx);
219 encd->contentInfo.ciphcx = NULL;
220 }
221
222 /* nothing to do after data */
223 return SECSuccess;
224}
225
226
227/*
228 * SecCmsEncryptedDataDecodeBeforeData - find bulk key & set up decryption
229 */
230OSStatus
231SecCmsEncryptedDataDecodeBeforeData(SecCmsEncryptedDataRef encd)
232{
233 SecSymmetricKeyRef bulkkey = NULL;
234 SecCmsContentInfoRef cinfo;
235 SECAlgorithmID *bulkalg;
236 OSStatus rv = SECFailure;
237
238 cinfo = &(encd->contentInfo);
239
240 bulkalg = SecCmsContentInfoGetContentEncAlg(cinfo);
241
d8f41ccd 242 if (encd->contentInfo.cmsg->decrypt_key_cb == NULL) /* no callback? no key../ */
b1ab9ed8
A
243 goto loser;
244
d8f41ccd 245 bulkkey = (*encd->contentInfo.cmsg->decrypt_key_cb)(encd->contentInfo.cmsg->decrypt_key_cb_arg, bulkalg);
b1ab9ed8
A
246 if (bulkkey == NULL)
247 /* no success finding a bulk key */
248 goto loser;
249
250 SecCmsContentInfoSetBulkKey(cinfo, bulkkey);
251
252 cinfo->ciphcx = SecCmsCipherContextStartDecrypt(bulkkey, bulkalg);
253 if (cinfo->ciphcx == NULL)
254 goto loser; /* error has been set by SecCmsCipherContextStartDecrypt */
255
256#if 1
257 // @@@ Not done yet
258#else
259 /*
260 * HACK ALERT!!
261 * For PKCS5 Encryption Algorithms, the bulkkey is actually a different
262 * structure. Therefore, we need to set the bulkkey to the actual key
263 * prior to freeing it.
264 */
265 if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) {
266 SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey;
267 bulkkey = keyPwd->key;
268 }
269#endif
270
271 /* we are done with (this) bulkkey now. */
272 CFRelease(bulkkey);
273
274 rv = SECSuccess;
275
276loser:
277 return rv;
278}
279
280/*
281 * SecCmsEncryptedDataDecodeAfterData - finish decrypting this encryptedData's content
282 */
283OSStatus
284SecCmsEncryptedDataDecodeAfterData(SecCmsEncryptedDataRef encd)
285{
286 if (encd->contentInfo.ciphcx) {
287 SecCmsCipherContextDestroy(encd->contentInfo.ciphcx);
288 encd->contentInfo.ciphcx = NULL;
289 }
290
291 return SECSuccess;
292}
293
294/*
295 * SecCmsEncryptedDataDecodeAfterEnd - finish decoding this encryptedData
296 */
297OSStatus
298SecCmsEncryptedDataDecodeAfterEnd(SecCmsEncryptedDataRef encd)
299{
300 /* apply final touches */
301 return SECSuccess;
302}