~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/pk11wrap/pk11sdr.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
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/
 
8
 *
 
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.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
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.
 
20
 *
 
21
 * Contributor(s):
 
22
 *   thayes@netscape.com
 
23
 *
 
24
 * Alternatively, the contents of this file may be used under the terms of
 
25
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
26
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
27
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
28
 * of those above. If you wish to allow use of your version of this file only
 
29
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
30
 * use your version of this file under the terms of the MPL, indicate your
 
31
 * decision by deleting the provisions above and replace them with the notice
 
32
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
33
 * the provisions above, a recipient may use your version of this file under
 
34
 * the terms of any one of the MPL, the GPL or the LGPL.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
#include "seccomon.h"
 
39
#include "secoid.h"
 
40
#include "secasn1.h"
 
41
#include "pkcs11.h"
 
42
#include "pk11func.h"
 
43
#include "pk11sdr.h"
 
44
 
 
45
/*
 
46
 * Data structure and template for encoding the result of an SDR operation
 
47
 *  This is temporary.  It should include the algorithm ID of the encryption mechanism
 
48
 */
 
49
struct SDRResult
 
50
{
 
51
  SECItem keyid;
 
52
  SECAlgorithmID alg;
 
53
  SECItem data;
 
54
};
 
55
typedef struct SDRResult SDRResult;
 
56
 
 
57
static SEC_ASN1Template template[] = {
 
58
  { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) },
 
59
  { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) },
 
60
  { SEC_ASN1_INLINE, offsetof(SDRResult, alg), SECOID_AlgorithmIDTemplate },
 
61
  { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) },
 
62
  { 0 }
 
63
};
 
64
 
 
65
static unsigned char keyID[] = {
 
66
  0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
67
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
 
68
};
 
69
 
 
70
static SECItem keyIDItem = {
 
71
  0,
 
72
  keyID,
 
73
  sizeof keyID
 
74
};
 
75
 
 
76
/* local utility function for padding an incoming data block
 
77
 * to the mechanism block size.
 
78
 */
 
79
static SECStatus
 
80
padBlock(SECItem *data, int blockSize, SECItem *result)
 
81
{
 
82
  SECStatus rv = SECSuccess;
 
83
  int padLength;
 
84
  unsigned int i;
 
85
 
 
86
  result->data = 0;
 
87
  result->len = 0;
 
88
 
 
89
  /* This algorithm always adds to the block (to indicate the number
 
90
   * of pad bytes).  So allocate a block large enough.
 
91
   */
 
92
  padLength = blockSize - (data->len % blockSize);
 
93
  result->len = data->len + padLength;
 
94
  result->data = (unsigned char *)PORT_Alloc(result->len);
 
95
 
 
96
  /* Copy the data */
 
97
  PORT_Memcpy(result->data, data->data, data->len);
 
98
 
 
99
  /* Add the pad values */
 
100
  for(i = data->len; i < result->len; i++)
 
101
    result->data[i] = (unsigned char)padLength;
 
102
 
 
103
  return rv;
 
104
}
 
105
 
 
106
static SECStatus
 
107
unpadBlock(SECItem *data, int blockSize, SECItem *result)
 
108
{
 
109
  SECStatus rv = SECSuccess;
 
110
  int padLength;
 
111
 
 
112
  result->data = 0;
 
113
  result->len = 0;
 
114
 
 
115
  /* Remove the padding from the end if the input data */
 
116
  if (data->len == 0 || data->len % blockSize  != 0) { rv = SECFailure; goto loser; }
 
117
 
 
118
  padLength = data->data[data->len-1];
 
119
  if (padLength > blockSize) { rv = SECFailure; goto loser; }
 
120
 
 
121
  result->len = data->len - padLength;
 
122
  result->data = (unsigned char *)PORT_Alloc(result->len);
 
123
  if (!result->data) { rv = SECFailure; goto loser; }
 
124
 
 
125
  PORT_Memcpy(result->data, data->data, result->len);
 
126
 
 
127
loser:
 
128
  return rv;
 
129
}
 
130
 
 
131
static PRLock *pk11sdrLock = NULL;
 
132
 
 
133
void
 
134
pk11sdr_Init (void)
 
135
{
 
136
   pk11sdrLock = PR_NewLock();
 
137
}
 
138
 
 
139
void
 
140
pk11sdr_Shutdown(void)
 
141
{
 
142
    if (pk11sdrLock) {
 
143
        PR_DestroyLock(pk11sdrLock);
 
144
        pk11sdrLock = NULL;
 
145
    }
 
146
}
 
147
 
 
148
/*
 
149
 * PK11SDR_Encrypt
 
150
 *  Encrypt a block of data using the symmetric key identified.  The result
 
151
 *  is an ASN.1 (DER) encoded block of keyid, params and data.
 
152
 */
 
153
SECStatus
 
154
PK11SDR_Encrypt(SECItem *keyid, SECItem *data, SECItem *result, void *cx)
 
155
{
 
156
  SECStatus rv = SECSuccess;
 
157
  PK11SlotInfo *slot = 0;
 
158
  PK11SymKey *key = 0;
 
159
  SECItem *params = 0;
 
160
  PK11Context *ctx = 0;
 
161
  CK_MECHANISM_TYPE type;
 
162
  SDRResult sdrResult;
 
163
  SECItem paddedData;
 
164
  SECItem *pKeyID;
 
165
  PLArenaPool *arena = 0;
 
166
 
 
167
  /* Initialize */
 
168
  paddedData.len = 0;
 
169
  paddedData.data = 0;
 
170
 
 
171
  arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
 
172
  if (!arena) { rv = SECFailure; goto loser; }
 
173
 
 
174
  /* 1. Locate the requested keyid, or the default key (which has a keyid)
 
175
   * 2. Create an encryption context
 
176
   * 3. Encrypt
 
177
   * 4. Encode the results (using ASN.1)
 
178
   */
 
179
 
 
180
  slot = PK11_GetInternalKeySlot();
 
181
  if (!slot) { rv = SECFailure; goto loser; }
 
182
 
 
183
  /* Use triple-DES */
 
184
  type = CKM_DES3_CBC;
 
185
 
 
186
  /*
 
187
   * Login to the internal token before we look for the key, otherwise we
 
188
   * won't find it.
 
189
   */
 
190
  rv = PK11_Authenticate(slot, PR_TRUE, cx);
 
191
  if (rv != SECSuccess) goto loser;
 
192
 
 
193
  /* Find the key to use */
 
194
  pKeyID = keyid;
 
195
  if (pKeyID->len == 0) {
 
196
          pKeyID = &keyIDItem;  /* Use default value */
 
197
 
 
198
          /* put in a course lock to prevent a race between not finding the 
 
199
           * key and creating  one.
 
200
           */
 
201
 
 
202
          if (pk11sdrLock) PR_Lock(pk11sdrLock);
 
203
 
 
204
          /* Try to find the key */
 
205
          key = PK11_FindFixedKey(slot, type, pKeyID, cx);
 
206
          
 
207
          /* If the default key doesn't exist yet, try to create it */
 
208
          if (!key) key = PK11_GenDES3TokenKey(slot, pKeyID, cx);
 
209
          if (pk11sdrLock) PR_Unlock(pk11sdrLock);
 
210
  } else {
 
211
          key = PK11_FindFixedKey(slot, type, pKeyID, cx);
 
212
  }
 
213
 
 
214
  if (!key) { rv = SECFailure; goto loser; }
 
215
 
 
216
  params = PK11_GenerateNewParam(type, key);
 
217
  if (!params) { rv = SECFailure; goto loser; }
 
218
 
 
219
  ctx = PK11_CreateContextBySymKey(type, CKA_ENCRYPT, key, params);
 
220
  if (!ctx) { rv = SECFailure; goto loser; }
 
221
 
 
222
  rv = padBlock(data, PK11_GetBlockSize(type, 0), &paddedData);
 
223
  if (rv != SECSuccess) goto loser;
 
224
 
 
225
  sdrResult.data.len = paddedData.len;
 
226
  sdrResult.data.data = (unsigned char *)PORT_ArenaAlloc(arena, sdrResult.data.len);
 
227
 
 
228
  rv = PK11_CipherOp(ctx, sdrResult.data.data, (int*)&sdrResult.data.len, sdrResult.data.len,
 
229
                     paddedData.data, paddedData.len);
 
230
  if (rv != SECSuccess) goto loser;
 
231
 
 
232
  PK11_Finalize(ctx);
 
233
 
 
234
  sdrResult.keyid = *pKeyID;
 
235
 
 
236
  rv = PK11_ParamToAlgid(SEC_OID_DES_EDE3_CBC, params, arena, &sdrResult.alg);
 
237
  if (rv != SECSuccess) goto loser;
 
238
 
 
239
  if (!SEC_ASN1EncodeItem(0, result, &sdrResult, template)) { rv = SECFailure; goto loser; }
 
240
 
 
241
loser:
 
242
  SECITEM_ZfreeItem(&paddedData, PR_FALSE);
 
243
  if (arena) PORT_FreeArena(arena, PR_TRUE);
 
244
  if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
 
245
  if (params) SECITEM_ZfreeItem(params, PR_TRUE);
 
246
  if (key) PK11_FreeSymKey(key);
 
247
  if (slot) PK11_FreeSlot(slot);
 
248
 
 
249
  return rv;
 
250
}
 
251
 
 
252
/*
 
253
 * PK11SDR_Decrypt
 
254
 *  Decrypt a block of data produced by PK11SDR_Encrypt.  The key used is identified
 
255
 *  by the keyid field within the input.
 
256
 */
 
257
SECStatus
 
258
PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx)
 
259
{
 
260
  SECStatus rv = SECSuccess;
 
261
  PK11SlotInfo *slot = 0;
 
262
  PK11SymKey *key = 0;
 
263
  PK11Context *ctx = 0;
 
264
  CK_MECHANISM_TYPE type;
 
265
  SDRResult sdrResult;
 
266
  SECItem *params = 0;
 
267
  SECItem paddedResult;
 
268
  PLArenaPool *arena = 0;
 
269
 
 
270
  paddedResult.len = 0;
 
271
  paddedResult.data = 0;
 
272
 
 
273
  arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
 
274
  if (!arena) { rv = SECFailure; goto loser; }
 
275
 
 
276
  /* Decode the incoming data */
 
277
  memset(&sdrResult, 0, sizeof sdrResult);
 
278
  rv = SEC_QuickDERDecodeItem(arena, &sdrResult, template, data);
 
279
  if (rv != SECSuccess) goto loser;  /* Invalid format */
 
280
 
 
281
  /* Find the slot and key for the given keyid */
 
282
  slot = PK11_GetInternalKeySlot();
 
283
  if (!slot) { rv = SECFailure; goto loser; }
 
284
 
 
285
  rv = PK11_Authenticate(slot, PR_TRUE, cx);
 
286
  if (rv != SECSuccess) goto loser;
 
287
 
 
288
  /* Use triple-DES (Should look up the algorithm) */
 
289
  type = CKM_DES3_CBC;
 
290
  key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx);
 
291
  if (!key) { rv = SECFailure; goto loser; }
 
292
 
 
293
  /* Get the parameter values from the data */
 
294
  params = PK11_ParamFromAlgid(&sdrResult.alg);
 
295
  if (!params) { rv = SECFailure; goto loser; }
 
296
 
 
297
  ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params);
 
298
  if (!ctx) { rv = SECFailure; goto loser; }
 
299
 
 
300
  paddedResult.len = sdrResult.data.len;
 
301
  paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len);
 
302
 
 
303
  rv = PK11_CipherOp(ctx, paddedResult.data, (int*)&paddedResult.len, paddedResult.len,
 
304
                     sdrResult.data.data, sdrResult.data.len);
 
305
  if (rv != SECSuccess) goto loser;
 
306
 
 
307
  PK11_Finalize(ctx);
 
308
 
 
309
  /* Remove the padding */
 
310
  rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result);
 
311
  if (rv) goto loser;
 
312
 
 
313
loser:
 
314
  /* SECITEM_ZfreeItem(&paddedResult, PR_FALSE); */
 
315
  if (arena) PORT_FreeArena(arena, PR_TRUE);
 
316
  if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
 
317
  if (key) PK11_FreeSymKey(key);
 
318
  if (params) SECITEM_ZfreeItem(params, PR_TRUE);
 
319
  if (slot) PK11_FreeSlot(slot);
 
320
 
 
321
  return rv;
 
322
}