Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / smime / cmsencdata.c
blob05079d2318c1711896f99ced7dee104c25f90111
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * CMS encryptedData methods.
40 * $Id: cmsencdata.c,v 1.8 2005/10/03 22:01:57 relyea%netscape.com Exp $
43 #include "cmslocal.h"
45 #include "key.h"
46 #include "secasn1.h"
47 #include "secitem.h"
48 #include "secoid.h"
49 #include "pk11func.h"
50 #include "prtime.h"
51 #include "secerr.h"
52 #include "secpkcs5.h"
55 * NSS_CMSEncryptedData_Create - create an empty encryptedData object.
57 * "algorithm" specifies the bulk encryption algorithm to use.
58 * "keysize" is the key size.
60 * An error results in a return value of NULL and an error set.
61 * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
63 NSSCMSEncryptedData *
64 NSS_CMSEncryptedData_Create(NSSCMSMessage *cmsg, SECOidTag algorithm, int keysize)
66 void *mark;
67 NSSCMSEncryptedData *encd;
68 PLArenaPool *poolp;
69 SECAlgorithmID *pbe_algid;
70 SECStatus rv;
72 poolp = cmsg->poolp;
74 mark = PORT_ArenaMark(poolp);
76 encd = (NSSCMSEncryptedData *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSEncryptedData));
77 if (encd == NULL)
78 goto loser;
80 encd->cmsg = cmsg;
82 /* version is set in NSS_CMSEncryptedData_Encode_BeforeStart() */
84 switch (algorithm) {
85 /* XXX hmmm... hardcoded algorithms? */
86 case SEC_OID_RC2_CBC:
87 case SEC_OID_DES_EDE3_CBC:
88 case SEC_OID_DES_CBC:
89 rv = NSS_CMSContentInfo_SetContentEncAlg(poolp, &(encd->contentInfo), algorithm, NULL, keysize);
90 break;
91 default:
92 /* Assume password-based-encryption. At least, try that. */
93 pbe_algid = PK11_CreatePBEAlgorithmID(algorithm, 1, NULL);
94 if (pbe_algid == NULL) {
95 rv = SECFailure;
96 break;
98 rv = NSS_CMSContentInfo_SetContentEncAlgID(poolp, &(encd->contentInfo), pbe_algid, keysize);
99 SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE);
100 break;
102 if (rv != SECSuccess)
103 goto loser;
105 PORT_ArenaUnmark(poolp, mark);
106 return encd;
108 loser:
109 PORT_ArenaRelease(poolp, mark);
110 return NULL;
114 * NSS_CMSEncryptedData_Destroy - destroy an encryptedData object
116 void
117 NSS_CMSEncryptedData_Destroy(NSSCMSEncryptedData *encd)
119 /* everything's in a pool, so don't worry about the storage */
120 NSS_CMSContentInfo_Destroy(&(encd->contentInfo));
121 return;
125 * NSS_CMSEncryptedData_GetContentInfo - return pointer to encryptedData object's contentInfo
127 NSSCMSContentInfo *
128 NSS_CMSEncryptedData_GetContentInfo(NSSCMSEncryptedData *encd)
130 return &(encd->contentInfo);
134 * NSS_CMSEncryptedData_Encode_BeforeStart - do all the necessary things to a EncryptedData
135 * before encoding begins.
137 * In particular:
138 * - set the correct version value.
139 * - get the encryption key
141 SECStatus
142 NSS_CMSEncryptedData_Encode_BeforeStart(NSSCMSEncryptedData *encd)
144 int version;
145 PK11SymKey *bulkkey = NULL;
146 SECItem *dummy;
147 NSSCMSContentInfo *cinfo = &(encd->contentInfo);
149 if (NSS_CMSArray_IsEmpty((void **)encd->unprotectedAttr))
150 version = NSS_CMS_ENCRYPTED_DATA_VERSION;
151 else
152 version = NSS_CMS_ENCRYPTED_DATA_VERSION_UPATTR;
154 dummy = SEC_ASN1EncodeInteger (encd->cmsg->poolp, &(encd->version), version);
155 if (dummy == NULL)
156 return SECFailure;
158 /* now get content encryption key (bulk key) by using our cmsg callback */
159 if (encd->cmsg->decrypt_key_cb)
160 bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg,
161 NSS_CMSContentInfo_GetContentEncAlg(cinfo));
162 if (bulkkey == NULL)
163 return SECFailure;
165 /* store the bulk key in the contentInfo so that the encoder can find it */
166 NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
167 PK11_FreeSymKey (bulkkey);
169 return SECSuccess;
173 * NSS_CMSEncryptedData_Encode_BeforeData - set up encryption
175 SECStatus
176 NSS_CMSEncryptedData_Encode_BeforeData(NSSCMSEncryptedData *encd)
178 NSSCMSContentInfo *cinfo;
179 PK11SymKey *bulkkey;
180 SECAlgorithmID *algid;
182 cinfo = &(encd->contentInfo);
184 /* find bulkkey and algorithm - must have been set by NSS_CMSEncryptedData_Encode_BeforeStart */
185 bulkkey = NSS_CMSContentInfo_GetBulkKey(cinfo);
186 if (bulkkey == NULL)
187 return SECFailure;
188 algid = NSS_CMSContentInfo_GetContentEncAlg(cinfo);
189 if (algid == NULL)
190 return SECFailure;
192 /* this may modify algid (with IVs generated in a token).
193 * it is therefore essential that algid is a pointer to the "real" contentEncAlg,
194 * not just to a copy */
195 cinfo->ciphcx = NSS_CMSCipherContext_StartEncrypt(encd->cmsg->poolp, bulkkey, algid);
196 PK11_FreeSymKey(bulkkey);
197 if (cinfo->ciphcx == NULL)
198 return SECFailure;
200 return SECSuccess;
204 * NSS_CMSEncryptedData_Encode_AfterData - finalize this encryptedData for encoding
206 SECStatus
207 NSS_CMSEncryptedData_Encode_AfterData(NSSCMSEncryptedData *encd)
209 if (encd->contentInfo.ciphcx) {
210 NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx);
211 encd->contentInfo.ciphcx = NULL;
214 /* nothing to do after data */
215 return SECSuccess;
220 * NSS_CMSEncryptedData_Decode_BeforeData - find bulk key & set up decryption
222 SECStatus
223 NSS_CMSEncryptedData_Decode_BeforeData(NSSCMSEncryptedData *encd)
225 PK11SymKey *bulkkey = NULL;
226 NSSCMSContentInfo *cinfo;
227 SECAlgorithmID *bulkalg;
228 SECStatus rv = SECFailure;
230 cinfo = &(encd->contentInfo);
232 bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo);
234 if (encd->cmsg->decrypt_key_cb == NULL) /* no callback? no key../ */
235 goto loser;
237 bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, bulkalg);
238 if (bulkkey == NULL)
239 /* no success finding a bulk key */
240 goto loser;
242 NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
244 cinfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
245 if (cinfo->ciphcx == NULL)
246 goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */
249 /* we are done with (this) bulkkey now. */
250 PK11_FreeSymKey(bulkkey);
252 rv = SECSuccess;
254 loser:
255 return rv;
259 * NSS_CMSEncryptedData_Decode_AfterData - finish decrypting this encryptedData's content
261 SECStatus
262 NSS_CMSEncryptedData_Decode_AfterData(NSSCMSEncryptedData *encd)
264 if (encd->contentInfo.ciphcx) {
265 NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx);
266 encd->contentInfo.ciphcx = NULL;
269 return SECSuccess;
273 * NSS_CMSEncryptedData_Decode_AfterEnd - finish decoding this encryptedData
275 SECStatus
276 NSS_CMSEncryptedData_Decode_AfterEnd(NSSCMSEncryptedData *encd)
278 /* apply final touches */
279 return SECSuccess;