~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/smime/cmsencdata.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 * $Id: cmsencdata.c,v 1.6 2003/02/10 22:36:45 relyea%netscape.com Exp $
 
38
 */
 
39
 
 
40
#include "cmslocal.h"
 
41
 
 
42
#include "key.h"
 
43
#include "secasn1.h"
 
44
#include "secitem.h"
 
45
#include "secoid.h"
 
46
#include "pk11func.h"
 
47
#include "prtime.h"
 
48
#include "secerr.h"
 
49
#include "secpkcs5.h"
 
50
 
 
51
/*
 
52
 * NSS_CMSEncryptedData_Create - 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
 */
 
60
NSSCMSEncryptedData *
 
61
NSS_CMSEncryptedData_Create(NSSCMSMessage *cmsg, SECOidTag algorithm, int keysize)
 
62
{
 
63
    void *mark;
 
64
    NSSCMSEncryptedData *encd;
 
65
    PLArenaPool *poolp;
 
66
    SECAlgorithmID *pbe_algid;
 
67
    SECStatus rv;
 
68
 
 
69
    poolp = cmsg->poolp;
 
70
 
 
71
    mark = PORT_ArenaMark(poolp);
 
72
 
 
73
    encd = (NSSCMSEncryptedData *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSEncryptedData));
 
74
    if (encd == NULL)
 
75
        goto loser;
 
76
 
 
77
    encd->cmsg = cmsg;
 
78
 
 
79
    /* version is set in NSS_CMSEncryptedData_Encode_BeforeStart() */
 
80
 
 
81
    switch (algorithm) {
 
82
    /* XXX hmmm... hardcoded algorithms? */
 
83
    case SEC_OID_RC2_CBC:
 
84
    case SEC_OID_DES_EDE3_CBC:
 
85
    case SEC_OID_DES_CBC:
 
86
        rv = NSS_CMSContentInfo_SetContentEncAlg(poolp, &(encd->contentInfo), algorithm, NULL, keysize);
 
87
        break;
 
88
    default:
 
89
        /* Assume password-based-encryption.  At least, try that. */
 
90
        pbe_algid = PK11_CreatePBEAlgorithmID(algorithm, 1, NULL);
 
91
        if (pbe_algid == NULL) {
 
92
            rv = SECFailure;
 
93
            break;
 
94
        }
 
95
        rv = NSS_CMSContentInfo_SetContentEncAlgID(poolp, &(encd->contentInfo), pbe_algid, keysize);
 
96
        SECOID_DestroyAlgorithmID (pbe_algid, PR_TRUE);
 
97
        break;
 
98
    }
 
99
    if (rv != SECSuccess)
 
100
        goto loser;
 
101
 
 
102
    PORT_ArenaUnmark(poolp, mark);
 
103
    return encd;
 
104
 
 
105
loser:
 
106
    PORT_ArenaRelease(poolp, mark);
 
107
    return NULL;
 
108
}
 
109
 
 
110
/*
 
111
 * NSS_CMSEncryptedData_Destroy - destroy an encryptedData object
 
112
 */
 
113
void
 
114
NSS_CMSEncryptedData_Destroy(NSSCMSEncryptedData *encd)
 
115
{
 
116
    /* everything's in a pool, so don't worry about the storage */
 
117
    NSS_CMSContentInfo_Destroy(&(encd->contentInfo));
 
118
    return;
 
119
}
 
120
 
 
121
/*
 
122
 * NSS_CMSEncryptedData_GetContentInfo - return pointer to encryptedData object's contentInfo
 
123
 */
 
124
NSSCMSContentInfo *
 
125
NSS_CMSEncryptedData_GetContentInfo(NSSCMSEncryptedData *encd)
 
126
{
 
127
    return &(encd->contentInfo);
 
128
}
 
129
 
 
130
/*
 
131
 * NSS_CMSEncryptedData_Encode_BeforeStart - do all the necessary things to a EncryptedData
 
132
 *     before encoding begins.
 
133
 *
 
134
 * In particular:
 
135
 *  - set the correct version value.
 
136
 *  - get the encryption key
 
137
 */
 
138
SECStatus
 
139
NSS_CMSEncryptedData_Encode_BeforeStart(NSSCMSEncryptedData *encd)
 
140
{
 
141
    int version;
 
142
    PK11SymKey *bulkkey = NULL;
 
143
    SECItem *dummy;
 
144
    NSSCMSContentInfo *cinfo = &(encd->contentInfo);
 
145
 
 
146
    if (NSS_CMSArray_IsEmpty((void **)encd->unprotectedAttr))
 
147
        version = NSS_CMS_ENCRYPTED_DATA_VERSION;
 
148
    else
 
149
        version = NSS_CMS_ENCRYPTED_DATA_VERSION_UPATTR;
 
150
    
 
151
    dummy = SEC_ASN1EncodeInteger (encd->cmsg->poolp, &(encd->version), version);
 
152
    if (dummy == NULL)
 
153
        return SECFailure;
 
154
 
 
155
    /* now get content encryption key (bulk key) by using our cmsg callback */
 
156
    if (encd->cmsg->decrypt_key_cb)
 
157
        bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, 
 
158
                    NSS_CMSContentInfo_GetContentEncAlg(cinfo));
 
159
    if (bulkkey == NULL)
 
160
        return SECFailure;
 
161
 
 
162
    /* store the bulk key in the contentInfo so that the encoder can find it */
 
163
    NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
 
164
    PK11_FreeSymKey (bulkkey);
 
165
 
 
166
    return SECSuccess;
 
167
}
 
168
 
 
169
/*
 
170
 * NSS_CMSEncryptedData_Encode_BeforeData - set up encryption
 
171
 */
 
172
SECStatus
 
173
NSS_CMSEncryptedData_Encode_BeforeData(NSSCMSEncryptedData *encd)
 
174
{
 
175
    NSSCMSContentInfo *cinfo;
 
176
    PK11SymKey *bulkkey;
 
177
    SECAlgorithmID *algid;
 
178
 
 
179
    cinfo = &(encd->contentInfo);
 
180
 
 
181
    /* find bulkkey and algorithm - must have been set by NSS_CMSEncryptedData_Encode_BeforeStart */
 
182
    bulkkey = NSS_CMSContentInfo_GetBulkKey(cinfo);
 
183
    if (bulkkey == NULL)
 
184
        return SECFailure;
 
185
    algid = NSS_CMSContentInfo_GetContentEncAlg(cinfo);
 
186
    if (algid == NULL)
 
187
        return SECFailure;
 
188
 
 
189
    /* this may modify algid (with IVs generated in a token).
 
190
     * it is therefore essential that algid is a pointer to the "real" contentEncAlg,
 
191
     * not just to a copy */
 
192
    cinfo->ciphcx = NSS_CMSCipherContext_StartEncrypt(encd->cmsg->poolp, bulkkey, algid);
 
193
    PK11_FreeSymKey(bulkkey);
 
194
    if (cinfo->ciphcx == NULL)
 
195
        return SECFailure;
 
196
 
 
197
    return SECSuccess;
 
198
}
 
199
 
 
200
/*
 
201
 * NSS_CMSEncryptedData_Encode_AfterData - finalize this encryptedData for encoding
 
202
 */
 
203
SECStatus
 
204
NSS_CMSEncryptedData_Encode_AfterData(NSSCMSEncryptedData *encd)
 
205
{
 
206
    if (encd->contentInfo.ciphcx) {
 
207
        NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx);
 
208
        encd->contentInfo.ciphcx = NULL;
 
209
    }
 
210
 
 
211
    /* nothing to do after data */
 
212
    return SECSuccess;
 
213
}
 
214
 
 
215
 
 
216
/*
 
217
 * NSS_CMSEncryptedData_Decode_BeforeData - find bulk key & set up decryption
 
218
 */
 
219
SECStatus
 
220
NSS_CMSEncryptedData_Decode_BeforeData(NSSCMSEncryptedData *encd)
 
221
{
 
222
    PK11SymKey *bulkkey = NULL;
 
223
    NSSCMSContentInfo *cinfo;
 
224
    SECAlgorithmID *bulkalg;
 
225
    SECStatus rv = SECFailure;
 
226
 
 
227
    cinfo = &(encd->contentInfo);
 
228
 
 
229
    bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo);
 
230
 
 
231
    if (encd->cmsg->decrypt_key_cb == NULL)     /* no callback? no key../ */
 
232
        goto loser;
 
233
 
 
234
    bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, bulkalg);
 
235
    if (bulkkey == NULL)
 
236
        /* no success finding a bulk key */
 
237
        goto loser;
 
238
 
 
239
    NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
 
240
 
 
241
    cinfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
 
242
    if (cinfo->ciphcx == NULL)
 
243
        goto loser;             /* error has been set by NSS_CMSCipherContext_StartDecrypt */
 
244
 
 
245
    /* 
 
246
     * HACK ALERT!!
 
247
     * For PKCS5 Encryption Algorithms, the bulkkey is actually a different
 
248
     * structure.  Therefore, we need to set the bulkkey to the actual key 
 
249
     * prior to freeing it.
 
250
     */
 
251
    if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) {
 
252
        SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey;
 
253
        bulkkey = keyPwd->key;
 
254
    }
 
255
 
 
256
    /* we are done with (this) bulkkey now. */
 
257
    PK11_FreeSymKey(bulkkey);
 
258
 
 
259
    rv = SECSuccess;
 
260
 
 
261
loser:
 
262
    return rv;
 
263
}
 
264
 
 
265
/*
 
266
 * NSS_CMSEncryptedData_Decode_AfterData - finish decrypting this encryptedData's content
 
267
 */
 
268
SECStatus
 
269
NSS_CMSEncryptedData_Decode_AfterData(NSSCMSEncryptedData *encd)
 
270
{
 
271
    if (encd->contentInfo.ciphcx) {
 
272
        NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx);
 
273
        encd->contentInfo.ciphcx = NULL;
 
274
    }
 
275
 
 
276
    return SECSuccess;
 
277
}
 
278
 
 
279
/*
 
280
 * NSS_CMSEncryptedData_Decode_AfterEnd - finish decoding this encryptedData
 
281
 */
 
282
SECStatus
 
283
NSS_CMSEncryptedData_Decode_AfterEnd(NSSCMSEncryptedData *encd)
 
284
{
 
285
    /* apply final touches */
 
286
    return SECSuccess;
 
287
}