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

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/pk11wrap/pk11akey.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
 *   Dr Stephen Henson <stephen.henson@gemplus.com>
 
23
 *   Dr Vipul Gupta <vipul.gupta@sun.com>, and
 
24
 *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
 
25
 *
 
26
 * Alternatively, the contents of this file may be used under the terms of
 
27
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
28
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
29
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
30
 * of those above. If you wish to allow use of your version of this file only
 
31
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
32
 * use your version of this file under the terms of the MPL, indicate your
 
33
 * decision by deleting the provisions above and replace them with the notice
 
34
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
35
 * the provisions above, a recipient may use your version of this file under
 
36
 * the terms of any one of the MPL, the GPL or the LGPL.
 
37
 *
 
38
 * ***** END LICENSE BLOCK ***** */
 
39
/*
 
40
 * This file contains functions to manage asymetric keys, (public and
 
41
 * private keys).
 
42
 */
 
43
#include "seccomon.h"
 
44
#include "secmod.h"
 
45
#include "secmodi.h"
 
46
#include "secmodti.h"
 
47
#include "pkcs11.h"
 
48
#include "pkcs11t.h"
 
49
#include "pk11func.h"
 
50
#include "cert.h"
 
51
#include "key.h"
 
52
#include "secitem.h"
 
53
#include "secasn1.h" 
 
54
#include "secoid.h" 
 
55
#include "secerr.h"
 
56
#include "sslerr.h"
 
57
#include "sechash.h"
 
58
 
 
59
#include "secpkcs5.h"  
 
60
#include "ec.h"
 
61
 
 
62
/*
 
63
 * import a public key into the desired slot
 
64
 */
 
65
CK_OBJECT_HANDLE
 
66
PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, 
 
67
                                                                PRBool isToken)
 
68
{
 
69
    CK_BBOOL cktrue = CK_TRUE;
 
70
    CK_BBOOL ckfalse = CK_FALSE;
 
71
    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
 
72
    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
 
73
    CK_OBJECT_HANDLE objectID;
 
74
    CK_ATTRIBUTE theTemplate[10];
 
75
    CK_ATTRIBUTE *signedattr = NULL;
 
76
    CK_ATTRIBUTE *attrs = theTemplate;
 
77
    int signedcount = 0;
 
78
    int templateCount = 0;
 
79
    SECStatus rv;
 
80
 
 
81
    /* if we already have an object in the desired slot, use it */
 
82
    if (!isToken && pubKey->pkcs11Slot == slot) {
 
83
        return pubKey->pkcs11ID;
 
84
    }
 
85
 
 
86
    /* free the existing key */
 
87
    if (pubKey->pkcs11Slot != NULL) {
 
88
        PK11SlotInfo *oSlot = pubKey->pkcs11Slot;
 
89
        PK11_EnterSlotMonitor(oSlot);
 
90
        (void) PK11_GETTAB(oSlot)->C_DestroyObject(oSlot->session,
 
91
                                                        pubKey->pkcs11ID);
 
92
        PK11_ExitSlotMonitor(oSlot);
 
93
        PK11_FreeSlot(oSlot);
 
94
        pubKey->pkcs11Slot = NULL;
 
95
    }
 
96
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++;
 
97
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++;
 
98
    PK11_SETATTRS(attrs, CKA_TOKEN, isToken ? &cktrue : &ckfalse,
 
99
                                                 sizeof(CK_BBOOL) ); attrs++;
 
100
 
 
101
    /* now import the key */
 
102
    {
 
103
        switch (pubKey->keyType) {
 
104
        case rsaKey:
 
105
            keyType = CKK_RSA;
 
106
            PK11_SETATTRS(attrs, CKA_WRAP, &cktrue, sizeof(CK_BBOOL) ); attrs++;
 
107
            PK11_SETATTRS(attrs, CKA_ENCRYPT, &cktrue, 
 
108
                                                sizeof(CK_BBOOL) ); attrs++;
 
109
            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL)); attrs++;
 
110
            signedattr = attrs;
 
111
            PK11_SETATTRS(attrs, CKA_MODULUS, pubKey->u.rsa.modulus.data,
 
112
                                         pubKey->u.rsa.modulus.len); attrs++;
 
113
            PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
 
114
                pubKey->u.rsa.publicExponent.data,
 
115
                                 pubKey->u.rsa.publicExponent.len); attrs++;
 
116
            break;
 
117
        case dsaKey:
 
118
            keyType = CKK_DSA;
 
119
            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
 
120
            signedattr = attrs;
 
121
            PK11_SETATTRS(attrs, CKA_PRIME,    pubKey->u.dsa.params.prime.data,
 
122
                                pubKey->u.dsa.params.prime.len); attrs++;
 
123
            PK11_SETATTRS(attrs,CKA_SUBPRIME,pubKey->u.dsa.params.subPrime.data,
 
124
                                pubKey->u.dsa.params.subPrime.len); attrs++;
 
125
            PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.dsa.params.base.data,
 
126
                                        pubKey->u.dsa.params.base.len); attrs++;
 
127
            PK11_SETATTRS(attrs, CKA_VALUE,    pubKey->u.dsa.publicValue.data, 
 
128
                                        pubKey->u.dsa.publicValue.len); attrs++;
 
129
            break;
 
130
        case fortezzaKey:
 
131
            keyType = CKK_DSA;
 
132
            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
 
133
            signedattr = attrs;
 
134
            PK11_SETATTRS(attrs, CKA_PRIME,pubKey->u.fortezza.params.prime.data,
 
135
                                pubKey->u.fortezza.params.prime.len); attrs++;
 
136
            PK11_SETATTRS(attrs,CKA_SUBPRIME,
 
137
                                pubKey->u.fortezza.params.subPrime.data,
 
138
                                pubKey->u.fortezza.params.subPrime.len);attrs++;
 
139
            PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.fortezza.params.base.data,
 
140
                                pubKey->u.fortezza.params.base.len); attrs++;
 
141
            PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.fortezza.DSSKey.data, 
 
142
                                pubKey->u.fortezza.DSSKey.len); attrs++;
 
143
            break;
 
144
        case dhKey:
 
145
            keyType = CKK_DH;
 
146
            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
 
147
            signedattr = attrs;
 
148
            PK11_SETATTRS(attrs, CKA_PRIME,    pubKey->u.dh.prime.data,
 
149
                                pubKey->u.dh.prime.len); attrs++;
 
150
            PK11_SETATTRS(attrs, CKA_BASE,  pubKey->u.dh.base.data,
 
151
                                        pubKey->u.dh.base.len); attrs++;
 
152
            PK11_SETATTRS(attrs, CKA_VALUE,    pubKey->u.dh.publicValue.data, 
 
153
                                        pubKey->u.dh.publicValue.len); attrs++;
 
154
            break;
 
155
        case ecKey:
 
156
            keyType = CKK_EC;
 
157
            PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++;
 
158
            PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));attrs++;
 
159
            signedattr = attrs;
 
160
            PK11_SETATTRS(attrs, CKA_EC_PARAMS, 
 
161
                          pubKey->u.ec.DEREncodedParams.data,
 
162
                          pubKey->u.ec.DEREncodedParams.len); attrs++;
 
163
            PK11_SETATTRS(attrs, CKA_EC_POINT, pubKey->u.ec.publicValue.data,
 
164
                          pubKey->u.ec.publicValue.len); attrs++;
 
165
            break;
 
166
        default:
 
167
            PORT_SetError( SEC_ERROR_BAD_KEY );
 
168
            return CK_INVALID_HANDLE;
 
169
        }
 
170
 
 
171
        templateCount = attrs - theTemplate;
 
172
        signedcount = attrs - signedattr;
 
173
        PORT_Assert(templateCount <= (sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)));
 
174
        for (attrs=signedattr; signedcount; attrs++, signedcount--) {
 
175
                pk11_SignedToUnsigned(attrs);
 
176
        } 
 
177
        rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate,
 
178
                                        templateCount, isToken, &objectID);
 
179
        if ( rv != SECSuccess) {
 
180
            return CK_INVALID_HANDLE;
 
181
        }
 
182
    }
 
183
 
 
184
    pubKey->pkcs11ID = objectID;
 
185
    pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
 
186
 
 
187
    return objectID;
 
188
}
 
189
 
 
190
/*
 
191
 * take an attribute and copy it into a secitem
 
192
 */
 
193
static CK_RV
 
194
pk11_Attr2SecItem(PRArenaPool *arena, CK_ATTRIBUTE *attr, SECItem *item) 
 
195
{
 
196
    item->data = NULL;
 
197
 
 
198
    (void)SECITEM_AllocItem(arena, item, attr->ulValueLen);
 
199
    if (item->data == NULL) {
 
200
        return CKR_HOST_MEMORY;
 
201
    } 
 
202
    PORT_Memcpy(item->data, attr->pValue, item->len);
 
203
    return CKR_OK;
 
204
}
 
205
 
 
206
/*
 
207
 * extract a public key from a slot and id
 
208
 */
 
209
SECKEYPublicKey *
 
210
PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id)
 
211
{
 
212
    CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
 
213
    PRArenaPool *arena;
 
214
    PRArenaPool *tmp_arena;
 
215
    SECKEYPublicKey *pubKey;
 
216
    int templateCount = 0;
 
217
    CK_KEY_TYPE pk11KeyType;
 
218
    CK_RV crv;
 
219
    CK_ATTRIBUTE template[8];
 
220
    CK_ATTRIBUTE *attrs= template;
 
221
    CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value;
 
222
    CK_ATTRIBUTE *ecparams;
 
223
 
 
224
    /* if we didn't know the key type, get it */
 
225
    if (keyType== nullKey) {
 
226
 
 
227
        pk11KeyType = PK11_ReadULongAttribute(slot,id,CKA_KEY_TYPE);
 
228
        if (pk11KeyType ==  CK_UNAVAILABLE_INFORMATION) {
 
229
            return NULL;
 
230
        }
 
231
        switch (pk11KeyType) {
 
232
        case CKK_RSA:
 
233
            keyType = rsaKey;
 
234
            break;
 
235
        case CKK_DSA:
 
236
            keyType = dsaKey;
 
237
            break;
 
238
        case CKK_DH:
 
239
            keyType = dhKey;
 
240
            break;
 
241
        case CKK_EC:
 
242
            keyType = ecKey;
 
243
            break;
 
244
        default:
 
245
            PORT_SetError( SEC_ERROR_BAD_KEY );
 
246
            return NULL;
 
247
        }
 
248
    }
 
249
 
 
250
 
 
251
    /* now we need to create space for the public key */
 
252
    arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
 
253
    if (arena == NULL) return NULL;
 
254
    tmp_arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
 
255
    if (tmp_arena == NULL) {
 
256
        PORT_FreeArena (arena, PR_FALSE);
 
257
        return NULL;
 
258
    }
 
259
 
 
260
 
 
261
    pubKey = (SECKEYPublicKey *) 
 
262
                        PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
 
263
    if (pubKey == NULL) {
 
264
        PORT_FreeArena (arena, PR_FALSE);
 
265
        PORT_FreeArena (tmp_arena, PR_FALSE);
 
266
        return NULL;
 
267
    }
 
268
 
 
269
    pubKey->arena = arena;
 
270
    pubKey->keyType = keyType;
 
271
    pubKey->pkcs11Slot = PK11_ReferenceSlot(slot);
 
272
    pubKey->pkcs11ID = id;
 
273
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, 
 
274
                                                sizeof(keyClass)); attrs++;
 
275
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &pk11KeyType, 
 
276
                                                sizeof(pk11KeyType) ); attrs++;
 
277
    switch (pubKey->keyType) {
 
278
    case rsaKey:
 
279
        modulus = attrs;
 
280
        PK11_SETATTRS(attrs, CKA_MODULUS, NULL, 0); attrs++; 
 
281
        exponent = attrs;
 
282
        PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, NULL, 0); attrs++; 
 
283
 
 
284
        templateCount = attrs - template;
 
285
        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
 
286
        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
 
287
        if (crv != CKR_OK) break;
 
288
 
 
289
        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_RSA)) {
 
290
            crv = CKR_OBJECT_HANDLE_INVALID;
 
291
            break;
 
292
        } 
 
293
        crv = pk11_Attr2SecItem(arena,modulus,&pubKey->u.rsa.modulus);
 
294
        if (crv != CKR_OK) break;
 
295
        crv = pk11_Attr2SecItem(arena,exponent,&pubKey->u.rsa.publicExponent);
 
296
        if (crv != CKR_OK) break;
 
297
        break;
 
298
    case dsaKey:
 
299
        prime = attrs;
 
300
        PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 
 
301
        subprime = attrs;
 
302
        PK11_SETATTRS(attrs, CKA_SUBPRIME, NULL, 0); attrs++; 
 
303
        base = attrs;
 
304
        PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 
 
305
        value = attrs;
 
306
        PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 
 
307
        templateCount = attrs - template;
 
308
        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
 
309
        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
 
310
        if (crv != CKR_OK) break;
 
311
 
 
312
        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DSA)) {
 
313
            crv = CKR_OBJECT_HANDLE_INVALID;
 
314
            break;
 
315
        } 
 
316
        crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dsa.params.prime);
 
317
        if (crv != CKR_OK) break;
 
318
        crv = pk11_Attr2SecItem(arena,subprime,&pubKey->u.dsa.params.subPrime);
 
319
        if (crv != CKR_OK) break;
 
320
        crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dsa.params.base);
 
321
        if (crv != CKR_OK) break;
 
322
        crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dsa.publicValue);
 
323
        if (crv != CKR_OK) break;
 
324
        break;
 
325
    case dhKey:
 
326
        prime = attrs;
 
327
        PK11_SETATTRS(attrs, CKA_PRIME, NULL, 0); attrs++; 
 
328
        base = attrs;
 
329
        PK11_SETATTRS(attrs, CKA_BASE, NULL, 0); attrs++; 
 
330
        value =attrs;
 
331
        PK11_SETATTRS(attrs, CKA_VALUE, NULL, 0); attrs++; 
 
332
        templateCount = attrs - template;
 
333
        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
 
334
        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
 
335
        if (crv != CKR_OK) break;
 
336
 
 
337
        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_DH)) {
 
338
            crv = CKR_OBJECT_HANDLE_INVALID;
 
339
            break;
 
340
        } 
 
341
        crv = pk11_Attr2SecItem(arena,prime,&pubKey->u.dh.prime);
 
342
        if (crv != CKR_OK) break;
 
343
        crv = pk11_Attr2SecItem(arena,base,&pubKey->u.dh.base);
 
344
        if (crv != CKR_OK) break;
 
345
        crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue);
 
346
        if (crv != CKR_OK) break;
 
347
        break;
 
348
    case ecKey:
 
349
        pubKey->u.ec.size = 0;
 
350
        ecparams = attrs;
 
351
        PK11_SETATTRS(attrs, CKA_EC_PARAMS, NULL, 0); attrs++; 
 
352
        value =attrs;
 
353
        PK11_SETATTRS(attrs, CKA_EC_POINT, NULL, 0); attrs++; 
 
354
        templateCount = attrs - template;
 
355
        PR_ASSERT(templateCount <= sizeof(template)/sizeof(CK_ATTRIBUTE));
 
356
        crv = PK11_GetAttributes(tmp_arena,slot,id,template,templateCount);
 
357
        if (crv != CKR_OK) break;
 
358
 
 
359
        if ((keyClass != CKO_PUBLIC_KEY) || (pk11KeyType != CKK_EC)) {
 
360
            crv = CKR_OBJECT_HANDLE_INVALID;
 
361
            break;
 
362
        } 
 
363
 
 
364
        crv = pk11_Attr2SecItem(arena,ecparams,
 
365
                                &pubKey->u.ec.DEREncodedParams);
 
366
        if (crv != CKR_OK) break;
 
367
        crv = pk11_Attr2SecItem(arena,value,&pubKey->u.ec.publicValue);
 
368
        if (crv != CKR_OK) break;
 
369
        break;
 
370
    case fortezzaKey:
 
371
    case nullKey:
 
372
    default:
 
373
        crv = CKR_OBJECT_HANDLE_INVALID;
 
374
        break;
 
375
    }
 
376
 
 
377
    PORT_FreeArena(tmp_arena,PR_FALSE);
 
378
 
 
379
    if (crv != CKR_OK) {
 
380
        PORT_FreeArena(arena,PR_FALSE);
 
381
        PK11_FreeSlot(slot);
 
382
        PORT_SetError( PK11_MapError(crv) );
 
383
        return NULL;
 
384
    }
 
385
 
 
386
    return pubKey;
 
387
}
 
388
 
 
389
/*
 
390
 * Build a Private Key structure from raw PKCS #11 information.
 
391
 */
 
392
SECKEYPrivateKey *
 
393
PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, 
 
394
                        PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
 
395
{
 
396
    PRArenaPool *arena;
 
397
    SECKEYPrivateKey *privKey;
 
398
    PRBool isPrivate;
 
399
    SECStatus rv;
 
400
 
 
401
    /* don't know? look it up */
 
402
    if (keyType == nullKey) {
 
403
        CK_KEY_TYPE pk11Type = CKK_RSA;
 
404
 
 
405
        pk11Type = PK11_ReadULongAttribute(slot,privID,CKA_KEY_TYPE);
 
406
        isTemp = (PRBool)!PK11_HasAttributeSet(slot,privID,CKA_TOKEN);
 
407
        switch (pk11Type) {
 
408
        case CKK_RSA: keyType = rsaKey; break;
 
409
        case CKK_DSA: keyType = dsaKey; break;
 
410
        case CKK_DH: keyType = dhKey; break;
 
411
        case CKK_KEA: keyType = fortezzaKey; break;
 
412
        case CKK_EC: keyType = ecKey; break;
 
413
        default:
 
414
                break;
 
415
        }
 
416
    }
 
417
 
 
418
    /* if the key is private, make sure we are authenticated to the
 
419
     * token before we try to use it */
 
420
    isPrivate = (PRBool)PK11_HasAttributeSet(slot,privID,CKA_PRIVATE);
 
421
    if (isPrivate) {
 
422
        rv = PK11_Authenticate(slot, PR_TRUE, wincx);
 
423
        if (rv != SECSuccess) {
 
424
            return NULL;
 
425
        }
 
426
    }
 
427
 
 
428
    /* now we need to create space for the private key */
 
429
    arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
 
430
    if (arena == NULL) return NULL;
 
431
 
 
432
    privKey = (SECKEYPrivateKey *) 
 
433
                        PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey));
 
434
    if (privKey == NULL) {
 
435
        PORT_FreeArena(arena, PR_FALSE);
 
436
        return NULL;
 
437
    }
 
438
 
 
439
    privKey->arena = arena;
 
440
    privKey->keyType = keyType;
 
441
    privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
 
442
    privKey->pkcs11ID = privID;
 
443
    privKey->pkcs11IsTemp = isTemp;
 
444
    privKey->wincx = wincx;
 
445
 
 
446
    return privKey;
 
447
}
 
448
 
 
449
 
 
450
PK11SlotInfo *
 
451
PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
 
452
{
 
453
    PK11SlotInfo *slot = key->pkcs11Slot;
 
454
    slot = PK11_ReferenceSlot(slot);
 
455
    return slot;
 
456
}
 
457
 
 
458
/*
 
459
 * Get the modulus length for raw parsing
 
460
 */
 
461
int
 
462
PK11_GetPrivateModulusLen(SECKEYPrivateKey *key)
 
463
{
 
464
    CK_ATTRIBUTE theTemplate = { CKA_MODULUS, NULL, 0 };
 
465
    PK11SlotInfo *slot = key->pkcs11Slot;
 
466
    CK_RV crv;
 
467
    int length;
 
468
 
 
469
    switch (key->keyType) {
 
470
    case rsaKey:
 
471
        crv = PK11_GetAttributes(NULL, slot, key->pkcs11ID, &theTemplate, 1);
 
472
        if (crv != CKR_OK) {
 
473
            PORT_SetError( PK11_MapError(crv) );
 
474
            return -1;
 
475
        }
 
476
        length = theTemplate.ulValueLen;
 
477
        if ( *(unsigned char *)theTemplate.pValue == 0) {
 
478
            length--;
 
479
        }
 
480
        if (theTemplate.pValue != NULL)
 
481
            PORT_Free(theTemplate.pValue);
 
482
        return (int) length;
 
483
        
 
484
    case fortezzaKey:
 
485
    case dsaKey:
 
486
    case dhKey:
 
487
    default:
 
488
        break;
 
489
    }
 
490
    if (theTemplate.pValue != NULL)
 
491
        PORT_Free(theTemplate.pValue);
 
492
    PORT_SetError( SEC_ERROR_INVALID_KEY );
 
493
    return -1;
 
494
}
 
495
 
 
496
 
 
497
 
 
498
/*
 
499
 * take a private key in one pkcs11 module and load it into another:
 
500
 *  NOTE: the source private key is a rare animal... it can't be sensitive.
 
501
 *  This is used to do a key gen using one pkcs11 module and storing the
 
502
 *  result into another.
 
503
 */
 
504
static SECKEYPrivateKey *
 
505
pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
 
506
                SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags) 
 
507
{
 
508
    CK_ATTRIBUTE privTemplate[] = {
 
509
        /* class must be first */
 
510
        { CKA_CLASS, NULL, 0 },
 
511
        { CKA_KEY_TYPE, NULL, 0 },
 
512
        { CKA_ID, NULL, 0 },
 
513
#ifdef notdef
 
514
        { CKA_LABEL, NULL, 0 },
 
515
        { CKA_SUBJECT, NULL, 0 },
 
516
#endif
 
517
        /* RSA */
 
518
        { CKA_MODULUS, NULL, 0 },
 
519
        { CKA_PRIVATE_EXPONENT, NULL, 0 },
 
520
        { CKA_PUBLIC_EXPONENT, NULL, 0 },
 
521
        { CKA_PRIME_1, NULL, 0 },
 
522
        { CKA_PRIME_2, NULL, 0 },
 
523
        { CKA_EXPONENT_1, NULL, 0 },
 
524
        { CKA_EXPONENT_2, NULL, 0 },
 
525
        { CKA_COEFFICIENT, NULL, 0 },
 
526
        /* reserve space for the attributes that may be
 
527
         * specified in attrFlags */
 
528
        { CKA_TOKEN, NULL, 0 },
 
529
        { CKA_PRIVATE, NULL, 0 },
 
530
        { CKA_MODIFIABLE, NULL, 0 },
 
531
        { CKA_SENSITIVE, NULL, 0 },
 
532
        { CKA_EXTRACTABLE, NULL, 0 },
 
533
#define NUM_RESERVED_ATTRS 5    /* number of reserved attributes above */
 
534
    };
 
535
    CK_BBOOL cktrue = CK_TRUE;
 
536
    CK_BBOOL ckfalse = CK_FALSE;
 
537
    CK_ATTRIBUTE *attrs = NULL, *ap;
 
538
    const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]);
 
539
    PRArenaPool *arena;
 
540
    CK_OBJECT_HANDLE objectID;
 
541
    int i, count = 0;
 
542
    int extra_count = 0;
 
543
    CK_RV crv;
 
544
    SECStatus rv;
 
545
    PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
 
546
 
 
547
    if (pk11_BadAttrFlags(attrFlags)) {
 
548
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
549
        return NULL;
 
550
    }
 
551
 
 
552
    for (i=0; i < templateSize; i++) {
 
553
        if (privTemplate[i].type == CKA_MODULUS) {
 
554
            attrs= &privTemplate[i];
 
555
            count = i;
 
556
            break;
 
557
        }
 
558
    }
 
559
    PORT_Assert(attrs != NULL);
 
560
    if (attrs == NULL) {
 
561
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
562
        return NULL;
 
563
    }
 
564
 
 
565
    ap = attrs;
 
566
 
 
567
    switch (privKey->keyType) {
 
568
    case rsaKey:
 
569
        count = templateSize - NUM_RESERVED_ATTRS;
 
570
        extra_count = count - (attrs - privTemplate);
 
571
        break;
 
572
    case dsaKey:
 
573
        ap->type = CKA_PRIME; ap++; count++; extra_count++;
 
574
        ap->type = CKA_SUBPRIME; ap++; count++; extra_count++;
 
575
        ap->type = CKA_BASE; ap++; count++; extra_count++;
 
576
        ap->type = CKA_VALUE; ap++; count++; extra_count++;
 
577
        break;
 
578
    case dhKey:
 
579
        ap->type = CKA_PRIME; ap++; count++; extra_count++;
 
580
        ap->type = CKA_BASE; ap++; count++; extra_count++;
 
581
        ap->type = CKA_VALUE; ap++; count++; extra_count++;
 
582
        break;
 
583
    case ecKey:
 
584
        ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++;
 
585
        ap->type = CKA_VALUE; ap++; count++; extra_count++;
 
586
        break;
 
587
     default:
 
588
        count = 0;
 
589
        extra_count = 0;
 
590
        break;
 
591
     }
 
592
 
 
593
     if (count == 0) {
 
594
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
595
        return NULL;
 
596
     }
 
597
 
 
598
     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
 
599
     if (arena == NULL) return NULL;
 
600
     /*
 
601
      * read out the old attributes.
 
602
      */
 
603
     crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID,
 
604
                privTemplate,count);
 
605
     if (crv != CKR_OK) {
 
606
        PORT_SetError( PK11_MapError(crv) );
 
607
        PORT_FreeArena(arena, PR_TRUE);
 
608
        return NULL;
 
609
     }
 
610
 
 
611
     /* Set token, private, modifiable, sensitive, and extractable */
 
612
     count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count],
 
613
                                        &cktrue, &ckfalse);
 
614
 
 
615
     /* Not everyone can handle zero padded key values, give
 
616
      * them the raw data as unsigned */
 
617
     for (ap=attrs; extra_count; ap++, extra_count--) {
 
618
        pk11_SignedToUnsigned(ap);
 
619
     }
 
620
 
 
621
     /* now Store the puppies */
 
622
     rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate, 
 
623
                                                count, token, &objectID);
 
624
     PORT_FreeArena(arena, PR_TRUE);
 
625
     if (rv != SECSuccess) {
 
626
        return NULL;
 
627
     }
 
628
 
 
629
     /* try loading the public key */
 
630
     if (pubKey) {
 
631
        PK11_ImportPublicKey(slot, pubKey, token);
 
632
        if (pubKey->pkcs11Slot) {
 
633
            PK11_FreeSlot(pubKey->pkcs11Slot);
 
634
            pubKey->pkcs11Slot = NULL;
 
635
            pubKey->pkcs11ID = CK_INVALID_HANDLE;
 
636
        }
 
637
     }
 
638
 
 
639
     /* build new key structure */
 
640
     return PK11_MakePrivKey(slot, privKey->keyType, !token, 
 
641
                                                objectID, privKey->wincx);
 
642
}
 
643
 
 
644
static SECKEYPrivateKey *
 
645
pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
 
646
                SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) 
 
647
{
 
648
    PK11AttrFlags attrFlags = 0;
 
649
    if (token) {
 
650
        attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE);
 
651
    } else {
 
652
        attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC);
 
653
    }
 
654
    if (sensitive) {
 
655
        attrFlags |= PK11_ATTR_SENSITIVE;
 
656
    } else {
 
657
        attrFlags |= PK11_ATTR_INSENSITIVE;
 
658
    }
 
659
    return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags);
 
660
}
 
661
 
 
662
/*
 
663
 * export this for PSM
 
664
 */
 
665
SECKEYPrivateKey *
 
666
PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, 
 
667
                SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) 
 
668
{
 
669
    return pk11_loadPrivKey(slot,privKey,pubKey,token,sensitive);
 
670
}
 
671
 
 
672
 
 
673
/*
 
674
 * Use the token to generate a key pair.
 
675
 */
 
676
SECKEYPrivateKey *
 
677
PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
 
678
   void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx)
 
679
{
 
680
    /* we have to use these native types because when we call PKCS 11 modules
 
681
     * we have to make sure that we are using the correct sizes for all the
 
682
     * parameters. */
 
683
    CK_BBOOL ckfalse = CK_FALSE;
 
684
    CK_BBOOL cktrue = CK_TRUE;
 
685
    CK_ULONG modulusBits;
 
686
    CK_BYTE publicExponent[4];
 
687
    CK_ATTRIBUTE privTemplate[] = {
 
688
        { CKA_SENSITIVE, NULL, 0},
 
689
        { CKA_TOKEN,  NULL, 0},
 
690
        { CKA_PRIVATE,  NULL, 0},
 
691
        { CKA_DERIVE,  NULL, 0},
 
692
        { CKA_UNWRAP,  NULL, 0},
 
693
        { CKA_SIGN,  NULL, 0},
 
694
        { CKA_DECRYPT,  NULL, 0},
 
695
        { CKA_EXTRACTABLE, NULL, 0},
 
696
        { CKA_MODIFIABLE,  NULL, 0},
 
697
    };
 
698
    CK_ATTRIBUTE rsaPubTemplate[] = {
 
699
        { CKA_MODULUS_BITS, NULL, 0},
 
700
        { CKA_PUBLIC_EXPONENT, NULL, 0},
 
701
        { CKA_TOKEN,  NULL, 0},
 
702
        { CKA_DERIVE,  NULL, 0},
 
703
        { CKA_WRAP,  NULL, 0},
 
704
        { CKA_VERIFY,  NULL, 0},
 
705
        { CKA_VERIFY_RECOVER,  NULL, 0},
 
706
        { CKA_ENCRYPT,  NULL, 0},
 
707
        { CKA_MODIFIABLE,  NULL, 0},
 
708
    };
 
709
    CK_ATTRIBUTE dsaPubTemplate[] = {
 
710
        { CKA_PRIME, NULL, 0 },
 
711
        { CKA_SUBPRIME, NULL, 0 },
 
712
        { CKA_BASE, NULL, 0 },
 
713
        { CKA_TOKEN,  NULL, 0},
 
714
        { CKA_DERIVE,  NULL, 0},
 
715
        { CKA_WRAP,  NULL, 0},
 
716
        { CKA_VERIFY,  NULL, 0},
 
717
        { CKA_VERIFY_RECOVER,  NULL, 0},
 
718
        { CKA_ENCRYPT,  NULL, 0},
 
719
        { CKA_MODIFIABLE,  NULL, 0},
 
720
    };
 
721
    CK_ATTRIBUTE dhPubTemplate[] = {
 
722
      { CKA_PRIME, NULL, 0 }, 
 
723
      { CKA_BASE, NULL, 0 }, 
 
724
      { CKA_TOKEN,  NULL, 0},
 
725
      { CKA_DERIVE,  NULL, 0},
 
726
      { CKA_WRAP,  NULL, 0},
 
727
      { CKA_VERIFY,  NULL, 0},
 
728
      { CKA_VERIFY_RECOVER,  NULL, 0},
 
729
      { CKA_ENCRYPT,  NULL, 0},
 
730
      { CKA_MODIFIABLE,  NULL, 0},
 
731
    };
 
732
    CK_ATTRIBUTE ecPubTemplate[] = {
 
733
      { CKA_EC_PARAMS, NULL, 0 }, 
 
734
      { CKA_TOKEN,  NULL, 0},
 
735
      { CKA_DERIVE,  NULL, 0},
 
736
      { CKA_WRAP,  NULL, 0},
 
737
      { CKA_VERIFY,  NULL, 0},
 
738
      { CKA_VERIFY_RECOVER,  NULL, 0},
 
739
      { CKA_ENCRYPT,  NULL, 0},
 
740
      { CKA_MODIFIABLE,  NULL, 0},
 
741
    };
 
742
    SECKEYECParams * ecParams;
 
743
 
 
744
    /*CK_ULONG key_size = 0;*/
 
745
    CK_ATTRIBUTE *pubTemplate;
 
746
    int privCount = 0;
 
747
    int pubCount = 0;
 
748
    PK11RSAGenParams *rsaParams;
 
749
    SECKEYPQGParams *dsaParams;
 
750
    SECKEYDHParams * dhParams;
 
751
    CK_MECHANISM mechanism;
 
752
    CK_MECHANISM test_mech;
 
753
    CK_SESSION_HANDLE session_handle;
 
754
    CK_RV crv;
 
755
    CK_OBJECT_HANDLE privID,pubID;
 
756
    SECKEYPrivateKey *privKey;
 
757
    KeyType keyType;
 
758
    PRBool restore;
 
759
    int peCount,i;
 
760
    CK_ATTRIBUTE *attrs;
 
761
    CK_ATTRIBUTE *privattrs;
 
762
    SECItem *pubKeyIndex;
 
763
    CK_ATTRIBUTE setTemplate;
 
764
    CK_MECHANISM_INFO mechanism_info;
 
765
    CK_OBJECT_CLASS keyClass;
 
766
    SECItem *cka_id;
 
767
    PRBool haslock = PR_FALSE;
 
768
    PRBool pubIsToken = PR_FALSE;
 
769
    PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0);
 
770
    /* subset of attrFlags applicable to the public key */
 
771
    PK11AttrFlags pubKeyAttrFlags = attrFlags &
 
772
        (PK11_ATTR_TOKEN | PK11_ATTR_SESSION
 
773
        | PK11_ATTR_MODIFIABLE | PK11_ATTR_UNMODIFIABLE);
 
774
 
 
775
    if (pk11_BadAttrFlags(attrFlags)) {
 
776
        PORT_SetError( SEC_ERROR_INVALID_ARGS );
 
777
        return NULL;
 
778
    }
 
779
 
 
780
    PORT_Assert(slot != NULL);
 
781
    if (slot == NULL) {
 
782
        PORT_SetError( SEC_ERROR_NO_MODULE);
 
783
        return NULL;
 
784
    }
 
785
 
 
786
    /* if our slot really doesn't do this mechanism, Generate the key
 
787
     * in our internal token and write it out */
 
788
    if (!PK11_DoesMechanism(slot,type)) {
 
789
        PK11SlotInfo *int_slot = PK11_GetInternalSlot();
 
790
 
 
791
        /* don't loop forever looking for a slot */
 
792
        if (slot == int_slot) {
 
793
            PK11_FreeSlot(int_slot);
 
794
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
 
795
            return NULL;
 
796
        }
 
797
 
 
798
        /* if there isn't a suitable slot, then we can't do the keygen */
 
799
        if (int_slot == NULL) {
 
800
            PORT_SetError( SEC_ERROR_NO_MODULE );
 
801
            return NULL;
 
802
        }
 
803
 
 
804
        /* generate the temporary key to load */
 
805
        privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE, 
 
806
                                                        PR_FALSE, wincx);
 
807
        PK11_FreeSlot(int_slot);
 
808
 
 
809
        /* if successful, load the temp key into the new token */
 
810
        if (privKey != NULL) {
 
811
            SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot,
 
812
                                                privKey,*pubKey,attrFlags);
 
813
            SECKEY_DestroyPrivateKey(privKey);
 
814
            if (newPrivKey == NULL) {
 
815
                SECKEY_DestroyPublicKey(*pubKey);
 
816
                *pubKey = NULL;
 
817
            }
 
818
            return newPrivKey;
 
819
        }
 
820
        return NULL;
 
821
   }
 
822
 
 
823
 
 
824
    mechanism.mechanism = type;
 
825
    mechanism.pParameter = NULL;
 
826
    mechanism.ulParameterLen = 0;
 
827
    test_mech.pParameter = NULL;
 
828
    test_mech.ulParameterLen = 0;
 
829
 
 
830
    /* set up the private key template */
 
831
    privattrs = privTemplate;
 
832
    privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs,
 
833
                                                &cktrue, &ckfalse);
 
834
 
 
835
    /* set up the mechanism specific info */
 
836
    switch (type) {
 
837
    case CKM_RSA_PKCS_KEY_PAIR_GEN:
 
838
    case CKM_RSA_X9_31_KEY_PAIR_GEN:
 
839
        rsaParams = (PK11RSAGenParams *)param;
 
840
        if (rsaParams->pe == 0) {
 
841
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
842
            return NULL;
 
843
        }
 
844
        modulusBits = rsaParams->keySizeInBits;
 
845
        peCount = 0;
 
846
 
 
847
        /* convert pe to a PKCS #11 string */
 
848
        for (i=0; i < 4; i++) {
 
849
            if (peCount || (rsaParams->pe & 
 
850
                                ((unsigned long)0xff000000L >> (i*8)))) {
 
851
                publicExponent[peCount] = 
 
852
                                (CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff);
 
853
                peCount++;
 
854
            }
 
855
        }
 
856
        PORT_Assert(peCount != 0);
 
857
        attrs = rsaPubTemplate;
 
858
        PK11_SETATTRS(attrs, CKA_MODULUS_BITS, 
 
859
                                &modulusBits, sizeof(modulusBits)); attrs++;
 
860
        PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, 
 
861
                                publicExponent, peCount);attrs++;
 
862
        pubTemplate = rsaPubTemplate;
 
863
        keyType = rsaKey;
 
864
        test_mech.mechanism = CKM_RSA_PKCS;
 
865
        break;
 
866
    case CKM_DSA_KEY_PAIR_GEN:
 
867
        dsaParams = (SECKEYPQGParams *)param;
 
868
        attrs = dsaPubTemplate;
 
869
        PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data,
 
870
                                dsaParams->prime.len); attrs++;
 
871
        PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data,
 
872
                                        dsaParams->subPrime.len); attrs++;
 
873
        PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data,
 
874
                                                dsaParams->base.len); attrs++;
 
875
        pubTemplate = dsaPubTemplate;
 
876
        keyType = dsaKey;
 
877
        test_mech.mechanism = CKM_DSA;
 
878
        break;
 
879
    case CKM_DH_PKCS_KEY_PAIR_GEN:
 
880
        dhParams = (SECKEYDHParams *)param;
 
881
        attrs = dhPubTemplate;
 
882
        PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data,
 
883
                      dhParams->prime.len);   attrs++;
 
884
        PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data,
 
885
                      dhParams->base.len);    attrs++;
 
886
        pubTemplate = dhPubTemplate;
 
887
        keyType = dhKey;
 
888
        test_mech.mechanism = CKM_DH_PKCS_DERIVE;
 
889
        break;
 
890
    case CKM_EC_KEY_PAIR_GEN:
 
891
        ecParams = (SECKEYECParams *)param;
 
892
        attrs = ecPubTemplate;
 
893
        PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, 
 
894
                      ecParams->len);   attrs++;
 
895
        pubTemplate = ecPubTemplate;
 
896
        keyType = ecKey;
 
897
        /* XXX An EC key can be used for other mechanisms too such
 
898
         * as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect
 
899
         * that in test_mech.mechanism so the CKA_SIGN, CKA_VERIFY
 
900
         * attributes are set correctly? 
 
901
         */
 
902
        test_mech.mechanism = CKM_ECDH1_DERIVE;
 
903
        break;
 
904
    default:
 
905
        PORT_SetError( SEC_ERROR_BAD_KEY );
 
906
        return NULL;
 
907
    }
 
908
 
 
909
    /* now query the slot to find out how "good" a key we can generate */
 
910
    if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
 
911
    crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
 
912
                                test_mech.mechanism,&mechanism_info);
 
913
    if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
 
914
    if ((crv != CKR_OK) || (mechanism_info.flags == 0)) {
 
915
        /* must be old module... guess what it should be... */
 
916
        switch (test_mech.mechanism) {
 
917
        case CKM_RSA_PKCS:
 
918
                mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT | 
 
919
                        CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);;
 
920
                break;
 
921
        case CKM_DSA:
 
922
                mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
 
923
                break;
 
924
        case CKM_DH_PKCS_DERIVE:
 
925
                mechanism_info.flags = CKF_DERIVE;
 
926
                break;
 
927
        case CKM_ECDH1_DERIVE:
 
928
                mechanism_info.flags = CKF_DERIVE;
 
929
                break;
 
930
        case CKM_ECDSA:
 
931
        case CKM_ECDSA_SHA1:
 
932
                mechanism_info.flags = CKF_SIGN | CKF_VERIFY;
 
933
                break;
 
934
        default:
 
935
               break;
 
936
        }
 
937
    }
 
938
    /* set the public key attributes */
 
939
    attrs += pk11_AttrFlagsToAttributes(pubKeyAttrFlags, attrs,
 
940
                                                &cktrue, &ckfalse);
 
941
    PK11_SETATTRS(attrs, CKA_DERIVE, 
 
942
                mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
 
943
                                         sizeof(CK_BBOOL)); attrs++;
 
944
    PK11_SETATTRS(attrs, CKA_WRAP, 
 
945
                mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse,
 
946
                                         sizeof(CK_BBOOL)); attrs++;
 
947
    PK11_SETATTRS(attrs, CKA_VERIFY, 
 
948
                mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse,
 
949
                                         sizeof(CK_BBOOL)); attrs++;
 
950
    PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER, 
 
951
                mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse,
 
952
                                         sizeof(CK_BBOOL)); attrs++;
 
953
    PK11_SETATTRS(attrs, CKA_ENCRYPT, 
 
954
                mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse,
 
955
                                         sizeof(CK_BBOOL)); attrs++;
 
956
    /* set the private key attributes */
 
957
    PK11_SETATTRS(privattrs, CKA_DERIVE, 
 
958
                mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse,
 
959
                                         sizeof(CK_BBOOL)); privattrs++;
 
960
    PK11_SETATTRS(privattrs, CKA_UNWRAP, 
 
961
                mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse,
 
962
                                         sizeof(CK_BBOOL)); privattrs++;
 
963
    PK11_SETATTRS(privattrs, CKA_SIGN, 
 
964
                mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse,
 
965
                                         sizeof(CK_BBOOL)); privattrs++;
 
966
    PK11_SETATTRS(privattrs, CKA_DECRYPT, 
 
967
                mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse,
 
968
                                         sizeof(CK_BBOOL)); privattrs++;
 
969
 
 
970
    if (token) {
 
971
        session_handle = PK11_GetRWSession(slot);
 
972
        haslock = PK11_RWSessionHasLock(slot,session_handle);
 
973
        restore = PR_TRUE;
 
974
    } else {
 
975
        session_handle = slot->session;
 
976
        if (session_handle != CK_INVALID_SESSION)
 
977
            PK11_EnterSlotMonitor(slot);
 
978
        restore = PR_FALSE;
 
979
        haslock = PR_TRUE;
 
980
    }
 
981
 
 
982
    if (session_handle == CK_INVALID_SESSION) {
 
983
        PORT_SetError(SEC_ERROR_BAD_DATA);
 
984
        return NULL;
 
985
    }
 
986
    privCount = privattrs - privTemplate;
 
987
    pubCount = attrs - pubTemplate;
 
988
    crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism,
 
989
        pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID);
 
990
 
 
991
    if (crv != CKR_OK) {
 
992
        if (restore)  {
 
993
            PK11_RestoreROSession(slot,session_handle);
 
994
        } else PK11_ExitSlotMonitor(slot);
 
995
        PORT_SetError( PK11_MapError(crv) );
 
996
        return NULL;
 
997
    }
 
998
    /* This locking code is dangerous and needs to be more thought
 
999
     * out... the real problem is that we're holding the mutex open this long
 
1000
     */
 
1001
    if (haslock) { PK11_ExitSlotMonitor(slot); }
 
1002
 
 
1003
    /* swap around the ID's for older PKCS #11 modules */
 
1004
    keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS);
 
1005
    if (keyClass != CKO_PUBLIC_KEY) {
 
1006
        CK_OBJECT_HANDLE tmp = pubID;
 
1007
        pubID = privID;
 
1008
        privID = tmp;
 
1009
    }
 
1010
 
 
1011
    *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID);
 
1012
    if (*pubKey == NULL) {
 
1013
        if (restore)  {
 
1014
            /* we may have to restore the mutex so it get's exited properly
 
1015
             * in RestoreROSession */
 
1016
            if (haslock)  PK11_EnterSlotMonitor(slot); 
 
1017
            PK11_RestoreROSession(slot,session_handle);
 
1018
        } 
 
1019
        PK11_DestroyObject(slot,pubID);
 
1020
        PK11_DestroyObject(slot,privID);
 
1021
        return NULL;
 
1022
    }
 
1023
 
 
1024
    /* set the ID to the public key so we can find it again */
 
1025
    pubKeyIndex =  NULL;
 
1026
    switch (type) {
 
1027
    case CKM_RSA_PKCS_KEY_PAIR_GEN:
 
1028
    case CKM_RSA_X9_31_KEY_PAIR_GEN:
 
1029
      pubKeyIndex = &(*pubKey)->u.rsa.modulus;
 
1030
      break;
 
1031
    case CKM_DSA_KEY_PAIR_GEN:
 
1032
      pubKeyIndex = &(*pubKey)->u.dsa.publicValue;
 
1033
      break;
 
1034
    case CKM_DH_PKCS_KEY_PAIR_GEN:
 
1035
      pubKeyIndex = &(*pubKey)->u.dh.publicValue;
 
1036
      break;      
 
1037
    case CKM_EC_KEY_PAIR_GEN:
 
1038
      pubKeyIndex = &(*pubKey)->u.ec.publicValue;
 
1039
      break;      
 
1040
    }
 
1041
    PORT_Assert(pubKeyIndex != NULL);
 
1042
 
 
1043
    cka_id = PK11_MakeIDFromPubKey(pubKeyIndex);
 
1044
    pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN);
 
1045
 
 
1046
    PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len);
 
1047
 
 
1048
    if (haslock) { PK11_EnterSlotMonitor(slot); }
 
1049
    crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID,
 
1050
                &setTemplate, 1);
 
1051
   
 
1052
    if (crv == CKR_OK && pubIsToken) {
 
1053
        crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID,
 
1054
                &setTemplate, 1);
 
1055
    }
 
1056
 
 
1057
 
 
1058
    if (restore) {
 
1059
        PK11_RestoreROSession(slot,session_handle);
 
1060
    } else {
 
1061
        PK11_ExitSlotMonitor(slot);
 
1062
    }
 
1063
    SECITEM_FreeItem(cka_id,PR_TRUE);
 
1064
 
 
1065
 
 
1066
    if (crv != CKR_OK) {
 
1067
        PK11_DestroyObject(slot,pubID);
 
1068
        PK11_DestroyObject(slot,privID);
 
1069
        PORT_SetError( PK11_MapError(crv) );
 
1070
        *pubKey = NULL;
 
1071
        return NULL;
 
1072
    }
 
1073
 
 
1074
    privKey = PK11_MakePrivKey(slot,keyType,!token,privID,wincx);
 
1075
    if (privKey == NULL) {
 
1076
        SECKEY_DestroyPublicKey(*pubKey);
 
1077
        PK11_DestroyObject(slot,privID);
 
1078
        *pubKey = NULL;
 
1079
        return NULL;
 
1080
    }
 
1081
 
 
1082
    return privKey;
 
1083
}
 
1084
 
 
1085
/*
 
1086
 * Use the token to generate a key pair.
 
1087
 */
 
1088
SECKEYPrivateKey *
 
1089
PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 
 
1090
   void *param, SECKEYPublicKey **pubKey, PRBool token, 
 
1091
                                        PRBool sensitive, void *wincx)
 
1092
{
 
1093
    PK11AttrFlags attrFlags = 0;
 
1094
 
 
1095
    if (token) {
 
1096
        attrFlags |= PK11_ATTR_TOKEN;
 
1097
    } else {
 
1098
        attrFlags |= PK11_ATTR_SESSION;
 
1099
    }
 
1100
    if (sensitive) {
 
1101
        attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE);
 
1102
    } else {
 
1103
        attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC);
 
1104
    }
 
1105
    return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey,
 
1106
                                                attrFlags, wincx);
 
1107
}
 
1108
 
 
1109
/* build a public KEA key from the public value */
 
1110
SECKEYPublicKey *
 
1111
PK11_MakeKEAPubKey(unsigned char *keyData,int length)
 
1112
{
 
1113
    SECKEYPublicKey *pubk;
 
1114
    SECItem pkData;
 
1115
    SECStatus rv;
 
1116
    PRArenaPool *arena;
 
1117
 
 
1118
    pkData.data = keyData;
 
1119
    pkData.len = length;
 
1120
 
 
1121
    arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
 
1122
    if (arena == NULL)
 
1123
        return NULL;
 
1124
 
 
1125
    pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
 
1126
    if (pubk == NULL) {
 
1127
        PORT_FreeArena (arena, PR_FALSE);
 
1128
        return NULL;
 
1129
    }
 
1130
 
 
1131
    pubk->arena = arena;
 
1132
    pubk->pkcs11Slot = 0;
 
1133
    pubk->pkcs11ID = CK_INVALID_HANDLE;
 
1134
    pubk->keyType = fortezzaKey;
 
1135
    rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData);
 
1136
    if (rv != SECSuccess) {
 
1137
        PORT_FreeArena (arena, PR_FALSE);
 
1138
        return NULL;
 
1139
    }
 
1140
    return pubk;
 
1141
}
 
1142
 
 
1143
SECStatus 
 
1144
PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
 
1145
                        SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
 
1146
                        SECItem *nickname, SECItem *publicValue, PRBool isPerm,
 
1147
                        PRBool isPrivate, KeyType keyType, 
 
1148
                        unsigned int keyUsage, void *wincx)
 
1149
{
 
1150
    CK_MECHANISM_TYPE mechanism;
 
1151
    SECItem *pbe_param, crypto_param;
 
1152
    PK11SymKey *key = NULL;
 
1153
    SECStatus rv = SECSuccess;
 
1154
    CK_MECHANISM cryptoMech, pbeMech;
 
1155
    CK_RV crv;
 
1156
    SECKEYPrivateKey *privKey = NULL;
 
1157
    PRBool faulty3DES = PR_FALSE;
 
1158
    int usageCount = 0;
 
1159
    CK_KEY_TYPE key_type;
 
1160
    CK_ATTRIBUTE_TYPE *usage = NULL;
 
1161
    CK_ATTRIBUTE_TYPE rsaUsage[] = {
 
1162
                 CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER };
 
1163
    CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN };
 
1164
    CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE };
 
1165
    CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE };
 
1166
    if((epki == NULL) || (pwitem == NULL))
 
1167
        return SECFailure;
 
1168
 
 
1169
    crypto_param.data = NULL;
 
1170
 
 
1171
    mechanism = PK11_AlgtagToMechanism(SECOID_FindOIDTag(
 
1172
                                        &epki->algorithm.algorithm));
 
1173
 
 
1174
    switch (keyType) {
 
1175
    default:
 
1176
    case rsaKey:
 
1177
        key_type = CKK_RSA;
 
1178
        switch  (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) {
 
1179
        case KU_KEY_ENCIPHERMENT:
 
1180
            usage = rsaUsage;
 
1181
            usageCount = 2;
 
1182
            break;
 
1183
        case KU_DIGITAL_SIGNATURE:
 
1184
            usage = &rsaUsage[2];
 
1185
            usageCount = 2;
 
1186
            break;
 
1187
        case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE:
 
1188
        case 0: /* default to everything */
 
1189
            usage = rsaUsage;
 
1190
            usageCount = 4;
 
1191
            break;
 
1192
        }
 
1193
        break;
 
1194
    case dhKey:
 
1195
        key_type = CKK_DH;
 
1196
        usage = dhUsage;
 
1197
        usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]);
 
1198
        break;
 
1199
    case dsaKey:
 
1200
        key_type = CKK_DSA;
 
1201
        usage = dsaUsage;
 
1202
        usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]);
 
1203
        break;
 
1204
    case ecKey:
 
1205
        key_type = CKK_EC;
 
1206
        switch  (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) {
 
1207
        case KU_DIGITAL_SIGNATURE:
 
1208
            usage = ecUsage;
 
1209
            usageCount = 1;
 
1210
            break;
 
1211
        case KU_KEY_AGREEMENT:
 
1212
            usage = &ecUsage[1];
 
1213
            usageCount = 1;
 
1214
            break;
 
1215
        case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT:
 
1216
        default: /* default to everything */
 
1217
            usage = ecUsage;
 
1218
            usageCount = 2;
 
1219
            break;
 
1220
        }
 
1221
        break;  
 
1222
    }
 
1223
 
 
1224
try_faulty_3des:
 
1225
    pbe_param = PK11_ParamFromAlgid(&epki->algorithm);
 
1226
 
 
1227
    key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem, 
 
1228
                                                        faulty3DES, wincx);
 
1229
    if((key == NULL) || (pbe_param == NULL)) {
 
1230
        rv = SECFailure;
 
1231
        goto done;
 
1232
    }
 
1233
 
 
1234
    pbeMech.mechanism = mechanism;
 
1235
    pbeMech.pParameter = pbe_param->data;
 
1236
    pbeMech.ulParameterLen = pbe_param->len;
 
1237
 
 
1238
    crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, 
 
1239
                                                pwitem, faulty3DES);
 
1240
    if(crv != CKR_OK) {
 
1241
        rv = SECFailure;
 
1242
        goto done;
 
1243
    }
 
1244
 
 
1245
    cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
 
1246
    crypto_param.data = (unsigned char*)cryptoMech.pParameter;
 
1247
    crypto_param.len = cryptoMech.ulParameterLen;
 
1248
 
 
1249
    PORT_Assert(usage != NULL);
 
1250
    PORT_Assert(usageCount != 0);
 
1251
    privKey = PK11_UnwrapPrivKey(slot, key, cryptoMech.mechanism, 
 
1252
                                 &crypto_param, &epki->encryptedData, 
 
1253
                                 nickname, publicValue, isPerm, isPrivate,
 
1254
                                 key_type, usage, usageCount, wincx);
 
1255
    if(privKey) {
 
1256
        SECKEY_DestroyPrivateKey(privKey);
 
1257
        privKey = NULL;
 
1258
        rv = SECSuccess;
 
1259
        goto done;
 
1260
    }
 
1261
 
 
1262
    /* if we are unable to import the key and the mechanism is 
 
1263
     * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that
 
1264
     * the encrypted blob was created with a buggy key generation method
 
1265
     * which is described in the PKCS 12 implementation notes.  So we
 
1266
     * need to try importing via that method.
 
1267
     */ 
 
1268
    if((mechanism == CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC) && (!faulty3DES)) {
 
1269
        /* clean up after ourselves before redoing the key generation. */
 
1270
 
 
1271
        PK11_FreeSymKey(key);
 
1272
        key = NULL;
 
1273
 
 
1274
        if(pbe_param) {
 
1275
            SECITEM_ZfreeItem(pbe_param, PR_TRUE);
 
1276
            pbe_param = NULL;
 
1277
        }
 
1278
 
 
1279
        if(crypto_param.data) {
 
1280
            SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
 
1281
            crypto_param.data = NULL;
 
1282
            cryptoMech.pParameter = NULL;
 
1283
            crypto_param.len = cryptoMech.ulParameterLen = 0;
 
1284
        }
 
1285
 
 
1286
        faulty3DES = PR_TRUE;
 
1287
        goto try_faulty_3des;
 
1288
    }
 
1289
 
 
1290
    /* key import really did fail */
 
1291
    rv = SECFailure;
 
1292
 
 
1293
done:
 
1294
    if(pbe_param != NULL) {
 
1295
        SECITEM_ZfreeItem(pbe_param, PR_TRUE);
 
1296
        pbe_param = NULL;
 
1297
    }
 
1298
 
 
1299
    if(crypto_param.data != NULL) {
 
1300
        SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
 
1301
    }
 
1302
 
 
1303
    if(key != NULL) {
 
1304
        PK11_FreeSymKey(key);
 
1305
    }
 
1306
 
 
1307
    return rv;
 
1308
}
 
1309
 
 
1310
SECKEYPrivateKeyInfo *
 
1311
PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
 
1312
{
 
1313
    return NULL;
 
1314
}
 
1315
 
 
1316
SECKEYEncryptedPrivateKeyInfo * 
 
1317
PK11_ExportEncryptedPrivKeyInfo(
 
1318
   PK11SlotInfo     *slot,      /* optional, encrypt key in this slot */
 
1319
   SECOidTag         algTag,    /* encrypt key with this algorithm */
 
1320
   SECItem          *pwitem,    /* password for PBE encryption */
 
1321
   SECKEYPrivateKey *pk,        /* encrypt this private key */
 
1322
   int               iteration, /* interations for PBE alg */
 
1323
   void             *wincx)     /* context for password callback ? */
 
1324
{
 
1325
    SECKEYEncryptedPrivateKeyInfo *epki      = NULL;
 
1326
    PRArenaPool                   *arena     = NULL;
 
1327
    SECAlgorithmID                *algid;
 
1328
    SECItem                       *pbe_param = NULL;
 
1329
    PK11SymKey                    *key       = NULL;
 
1330
    SECStatus                      rv        = SECSuccess;
 
1331
    CK_RV                          crv;
 
1332
    CK_ULONG                       encBufLen;
 
1333
    CK_MECHANISM_TYPE              mechanism;
 
1334
    CK_MECHANISM                   pbeMech;
 
1335
    CK_MECHANISM                   cryptoMech;
 
1336
    SECItem                        crypto_param;
 
1337
 
 
1338
    if (!pwitem || !pk) {
 
1339
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
 
1340
        return NULL;
 
1341
    }
 
1342
 
 
1343
    algid = SEC_PKCS5CreateAlgorithmID(algTag, NULL, iteration);
 
1344
    if (algid == NULL) {
 
1345
        return NULL;
 
1346
    }
 
1347
 
 
1348
    crypto_param.data = NULL;
 
1349
 
 
1350
    arena = PORT_NewArena(2048);
 
1351
    if (arena)
 
1352
        epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo);
 
1353
    if(epki == NULL) {
 
1354
        rv = SECFailure;
 
1355
        goto loser;
 
1356
    }
 
1357
    epki->arena = arena;
 
1358
 
 
1359
    mechanism = PK11_AlgtagToMechanism(algTag);
 
1360
    pbe_param = PK11_ParamFromAlgid(algid);
 
1361
    if (!pbe_param || mechanism == CKM_INVALID_MECHANISM) {
 
1362
        rv = SECFailure;
 
1363
        goto loser;
 
1364
    }
 
1365
    pbeMech.mechanism = mechanism;
 
1366
    pbeMech.pParameter = pbe_param->data;
 
1367
    pbeMech.ulParameterLen = pbe_param->len;
 
1368
 
 
1369
    /* if we didn't specify a slot, use the slot the private key was in */
 
1370
    if (!slot) {
 
1371
        slot = pk->pkcs11Slot;
 
1372
    }
 
1373
 
 
1374
    /* if we specified a different slot, and the private key slot can do the
 
1375
     * pbe key gen, generate the key in the private key slot so we don't have 
 
1376
     * to move it later */
 
1377
    if (slot != pk->pkcs11Slot) {
 
1378
        if (PK11_DoesMechanism(pk->pkcs11Slot,mechanism)) {
 
1379
            slot = pk->pkcs11Slot;
 
1380
        }
 
1381
    }
 
1382
    key = PK11_RawPBEKeyGen(slot, mechanism, pbe_param, pwitem, 
 
1383
                                                        PR_FALSE, wincx);
 
1384
 
 
1385
    if((key == NULL) || (pbe_param == NULL)) {
 
1386
        rv = SECFailure;
 
1387
        goto loser;
 
1388
    }
 
1389
 
 
1390
    crv = PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, 
 
1391
                                                pwitem, PR_FALSE);
 
1392
    if(crv != CKR_OK) {
 
1393
        rv = SECFailure;
 
1394
        goto loser;
 
1395
    }
 
1396
    cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMech.mechanism);
 
1397
    crypto_param.data = (unsigned char *)cryptoMech.pParameter;
 
1398
    crypto_param.len = cryptoMech.ulParameterLen;
 
1399
 
 
1400
    /* If the key isn't in the private key slot, move it */
 
1401
    if (key->slot != pk->pkcs11Slot) {
 
1402
        PK11SymKey *newkey = pk11_CopyToSlot(pk->pkcs11Slot,
 
1403
                                                key->type, CKA_WRAP, key);
 
1404
        if (newkey == NULL) {
 
1405
            rv= SECFailure;
 
1406
            goto loser;
 
1407
        }
 
1408
 
 
1409
        /* free the old key and use the new key */
 
1410
        PK11_FreeSymKey(key);
 
1411
        key = newkey;
 
1412
    }
 
1413
        
 
1414
    /* we are extracting an encrypted privateKey structure.
 
1415
     * which needs to be freed along with the buffer into which it is
 
1416
     * returned.  eventually, we should retrieve an encrypted key using
 
1417
     * pkcs8/pkcs5.
 
1418
     */
 
1419
    encBufLen = 0;
 
1420
    PK11_EnterSlotMonitor(pk->pkcs11Slot);
 
1421
    crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, 
 
1422
                &cryptoMech, key->objectID, pk->pkcs11ID, NULL, 
 
1423
                &encBufLen); 
 
1424
    PK11_ExitSlotMonitor(pk->pkcs11Slot);
 
1425
    if (crv != CKR_OK) {
 
1426
        rv = SECFailure;
 
1427
        goto loser;
 
1428
    }
 
1429
    epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen);
 
1430
    if (!epki->encryptedData.data) {
 
1431
        rv = SECFailure;
 
1432
        goto loser;
 
1433
    }
 
1434
    PK11_EnterSlotMonitor(pk->pkcs11Slot);
 
1435
    crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, 
 
1436
                &cryptoMech, key->objectID, pk->pkcs11ID, 
 
1437
                epki->encryptedData.data, &encBufLen); 
 
1438
    PK11_ExitSlotMonitor(pk->pkcs11Slot);
 
1439
    epki->encryptedData.len = (unsigned int) encBufLen;
 
1440
    if(crv != CKR_OK) {
 
1441
        rv = SECFailure;
 
1442
        goto loser;
 
1443
    }
 
1444
 
 
1445
    if(!epki->encryptedData.len) {
 
1446
        rv = SECFailure;
 
1447
        goto loser;
 
1448
    }
 
1449
 
 
1450
    rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid);
 
1451
 
 
1452
loser:
 
1453
    if(pbe_param != NULL) {
 
1454
        SECITEM_ZfreeItem(pbe_param, PR_TRUE);
 
1455
        pbe_param = NULL;
 
1456
    }
 
1457
 
 
1458
    if(crypto_param.data != NULL) {
 
1459
        SECITEM_ZfreeItem(&crypto_param, PR_FALSE);
 
1460
        crypto_param.data = NULL;
 
1461
    }
 
1462
 
 
1463
    if(key != NULL) {
 
1464
        PK11_FreeSymKey(key);
 
1465
    }
 
1466
    SECOID_DestroyAlgorithmID(algid, PR_TRUE);
 
1467
 
 
1468
    if(rv == SECFailure) {
 
1469
        if(arena != NULL) {
 
1470
            PORT_FreeArena(arena, PR_TRUE);
 
1471
        }
 
1472
        epki = NULL;
 
1473
    }
 
1474
 
 
1475
    return epki;
 
1476
}
 
1477
 
 
1478
SECKEYEncryptedPrivateKeyInfo * 
 
1479
PK11_ExportEncryptedPrivateKeyInfo(
 
1480
   PK11SlotInfo    *slot,      /* optional, encrypt key in this slot */
 
1481
   SECOidTag        algTag,    /* encrypt key with this algorithm */
 
1482
   SECItem         *pwitem,    /* password for PBE encryption */
 
1483
   CERTCertificate *cert,      /* wrap priv key for this user cert */
 
1484
   int              iteration, /* interations for PBE alg */
 
1485
   void            *wincx)     /* context for password callback ? */
 
1486
{
 
1487
    SECKEYEncryptedPrivateKeyInfo *epki = NULL;
 
1488
    SECKEYPrivateKey              *pk   = PK11_FindKeyByAnyCert(cert, wincx);
 
1489
    if (pk != NULL) {
 
1490
        epki = PK11_ExportEncryptedPrivKeyInfo(slot, algTag, pwitem, pk, 
 
1491
                                               iteration, wincx);
 
1492
        SECKEY_DestroyPrivateKey(pk);
 
1493
    }
 
1494
    return epki;
 
1495
}
 
1496
 
 
1497
SECItem*
 
1498
PK11_DEREncodePublicKey(SECKEYPublicKey *pubk)
 
1499
{
 
1500
    CERTSubjectPublicKeyInfo *spki=NULL;
 
1501
    SECItem *spkiDER = NULL;
 
1502
 
 
1503
    if( pubk == NULL ) {
 
1504
        return NULL;
 
1505
    }
 
1506
 
 
1507
    /* get the subjectpublickeyinfo */
 
1508
    spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
 
1509
    if( spki == NULL ) {
 
1510
        goto finish;
 
1511
    }
 
1512
 
 
1513
    /* DER-encode the subjectpublickeyinfo */
 
1514
    spkiDER = SEC_ASN1EncodeItem(NULL /*arena*/, NULL/*dest*/, spki,
 
1515
                    CERT_SubjectPublicKeyInfoTemplate);
 
1516
 
 
1517
finish:
 
1518
    return spkiDER;
 
1519
}
 
1520
 
 
1521
char *
 
1522
PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey)
 
1523
{
 
1524
    return PK11_GetObjectNickname(privKey->pkcs11Slot,privKey->pkcs11ID);
 
1525
}
 
1526
 
 
1527
char *
 
1528
PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey)
 
1529
{
 
1530
    return PK11_GetObjectNickname(pubKey->pkcs11Slot,pubKey->pkcs11ID);
 
1531
}
 
1532
 
 
1533
SECStatus
 
1534
PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey, const char *nickname)
 
1535
{
 
1536
    return PK11_SetObjectNickname(privKey->pkcs11Slot,
 
1537
                                        privKey->pkcs11ID,nickname);
 
1538
}
 
1539
 
 
1540
SECStatus
 
1541
PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey, const char *nickname)
 
1542
{
 
1543
    return PK11_SetObjectNickname(pubKey->pkcs11Slot,
 
1544
                                        pubKey->pkcs11ID,nickname);
 
1545
}
 
1546
 
 
1547
SECKEYPQGParams *
 
1548
PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey)
 
1549
{
 
1550
    CK_ATTRIBUTE pTemplate[] = {
 
1551
        { CKA_PRIME, NULL, 0 },
 
1552
        { CKA_SUBPRIME, NULL, 0 },
 
1553
        { CKA_BASE, NULL, 0 },
 
1554
    };
 
1555
    int pTemplateLen = sizeof(pTemplate)/sizeof(pTemplate[0]);
 
1556
    PRArenaPool *arena = NULL;
 
1557
    SECKEYPQGParams *params;
 
1558
    CK_RV crv;
 
1559
 
 
1560
 
 
1561
    arena = PORT_NewArena(2048);
 
1562
    if (arena == NULL) {
 
1563
        goto loser;
 
1564
    }
 
1565
    params=(SECKEYPQGParams *)PORT_ArenaZAlloc(arena,sizeof(SECKEYPQGParams));
 
1566
    if (params == NULL) {
 
1567
        goto loser;
 
1568
    }
 
1569
 
 
1570
    crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, 
 
1571
                                                pTemplate, pTemplateLen);
 
1572
    if (crv != CKR_OK) {
 
1573
        PORT_SetError( PK11_MapError(crv) );
 
1574
        goto loser;
 
1575
    }
 
1576
 
 
1577
    params->arena = arena;
 
1578
    params->prime.data = pTemplate[0].pValue;
 
1579
    params->prime.len = pTemplate[0].ulValueLen;
 
1580
    params->subPrime.data = pTemplate[1].pValue;
 
1581
    params->subPrime.len = pTemplate[1].ulValueLen;
 
1582
    params->base.data = pTemplate[2].pValue;
 
1583
    params->base.len = pTemplate[2].ulValueLen;
 
1584
 
 
1585
    return params;
 
1586
 
 
1587
loser:
 
1588
    if (arena != NULL) {
 
1589
        PORT_FreeArena(arena,PR_FALSE);
 
1590
    }
 
1591
    return NULL;
 
1592
}
 
1593
 
 
1594
SECKEYPrivateKey*
 
1595
PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
 
1596
                                      SECKEYPrivateKey *privKey)
 
1597
{
 
1598
    CK_RV             crv;
 
1599
    CK_OBJECT_HANDLE  newKeyID;
 
1600
 
 
1601
    static const CK_BBOOL     ckfalse = CK_FALSE;
 
1602
    static const CK_ATTRIBUTE template[1] = { 
 
1603
       { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse }
 
1604
    };
 
1605
 
 
1606
    if (destSlot && destSlot != privKey->pkcs11Slot) {
 
1607
        SECKEYPrivateKey *newKey =
 
1608
               pk11_loadPrivKey(destSlot, 
 
1609
                                privKey, 
 
1610
                                NULL,     /* pubKey    */
 
1611
                                PR_FALSE, /* token     */
 
1612
                                PR_FALSE);/* sensitive */
 
1613
        if (newKey)
 
1614
            return newKey;
 
1615
    }
 
1616
    destSlot = privKey->pkcs11Slot;
 
1617
    PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx);
 
1618
    PK11_EnterSlotMonitor(destSlot);
 
1619
    crv = PK11_GETTAB(destSlot)->C_CopyObject(  destSlot->session, 
 
1620
                                                privKey->pkcs11ID,
 
1621
                                                (CK_ATTRIBUTE *)template, 
 
1622
                                                1, &newKeyID);
 
1623
    PK11_ExitSlotMonitor(destSlot);
 
1624
 
 
1625
    if (crv != CKR_OK) {
 
1626
        PORT_SetError( PK11_MapError(crv) );
 
1627
        return NULL;
 
1628
    }
 
1629
 
 
1630
    return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/, 
 
1631
                            newKeyID, privKey->wincx);
 
1632
}
 
1633
 
 
1634
SECKEYPrivateKey*
 
1635
PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx)
 
1636
{
 
1637
    PK11SlotInfo* slot = privk->pkcs11Slot;
 
1638
    CK_ATTRIBUTE template[1];
 
1639
    CK_ATTRIBUTE *attrs = template;
 
1640
    CK_BBOOL cktrue = CK_TRUE;
 
1641
    CK_RV crv;
 
1642
    CK_OBJECT_HANDLE newKeyID;
 
1643
    CK_SESSION_HANDLE rwsession;
 
1644
 
 
1645
    PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
 
1646
 
 
1647
    PK11_Authenticate(slot, PR_TRUE, wincx);
 
1648
    rwsession = PK11_GetRWSession(slot);
 
1649
    if (rwsession == CK_INVALID_SESSION) {
 
1650
        PORT_SetError(SEC_ERROR_BAD_DATA);
 
1651
        return NULL;
 
1652
    }
 
1653
    crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID,
 
1654
        template, 1, &newKeyID);
 
1655
    PK11_RestoreROSession(slot, rwsession);
 
1656
 
 
1657
    if (crv != CKR_OK) {
 
1658
        PORT_SetError( PK11_MapError(crv) );
 
1659
        return NULL;
 
1660
    }
 
1661
 
 
1662
    return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
 
1663
        newKeyID, NULL /*wincx*/);
 
1664
}
 
1665
 
 
1666
/*
 
1667
 * destroy a private key if there are no matching certs.
 
1668
 * this function also frees the privKey structure.
 
1669
 */
 
1670
SECStatus
 
1671
PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force)
 
1672
{
 
1673
    CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);
 
1674
 
 
1675
    /* found a cert matching the private key?. */
 
1676
    if (!force  && cert != NULL) {
 
1677
        /* yes, don't delete the key */
 
1678
        CERT_DestroyCertificate(cert);
 
1679
        SECKEY_DestroyPrivateKey(privKey);
 
1680
        return SECWouldBlock;
 
1681
    }
 
1682
    /* now, then it's safe for the key to go away */
 
1683
    PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);
 
1684
    SECKEY_DestroyPrivateKey(privKey);
 
1685
    return SECSuccess;
 
1686
}
 
1687
 
 
1688
/*
 
1689
 * destroy a private key if there are no matching certs.
 
1690
 * this function also frees the privKey structure.
 
1691
 */
 
1692
SECStatus
 
1693
PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey)
 
1694
{
 
1695
    /* now, then it's safe for the key to go away */
 
1696
    if (pubKey->pkcs11Slot == NULL) {
 
1697
        return SECFailure;
 
1698
    }
 
1699
    PK11_DestroyTokenObject(pubKey->pkcs11Slot,pubKey->pkcs11ID);
 
1700
    SECKEY_DestroyPublicKey(pubKey);
 
1701
    return SECSuccess;
 
1702
}
 
1703
 
 
1704
/*
 
1705
 * key call back structure.
 
1706
 */
 
1707
typedef struct pk11KeyCallbackStr {
 
1708
        SECStatus (* callback)(SECKEYPrivateKey *,void *);
 
1709
        void *callbackArg;
 
1710
        void *wincx;
 
1711
} pk11KeyCallback;
 
1712
 
 
1713
/*
 
1714
 * callback to map Object Handles to Private Keys;
 
1715
 */
 
1716
SECStatus
 
1717
pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
 
1718
{
 
1719
    SECStatus rv = SECSuccess;
 
1720
    SECKEYPrivateKey *privKey;
 
1721
    pk11KeyCallback *keycb = (pk11KeyCallback *) arg;
 
1722
    if (!arg) {
 
1723
        return SECFailure;
 
1724
    }
 
1725
 
 
1726
    privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);
 
1727
 
 
1728
    if (privKey == NULL) {
 
1729
        return SECFailure;
 
1730
    }
 
1731
 
 
1732
    if (keycb->callback) {
 
1733
        rv = (*keycb->callback)(privKey,keycb->callbackArg);
 
1734
    }
 
1735
 
 
1736
    SECKEY_DestroyPrivateKey(privKey);      
 
1737
    return rv;
 
1738
}
 
1739
 
 
1740
/***********************************************************************
 
1741
 * PK11_TraversePrivateKeysInSlot
 
1742
 *
 
1743
 * Traverses all the private keys on a slot.
 
1744
 *
 
1745
 * INPUTS
 
1746
 *      slot
 
1747
 *          The PKCS #11 slot whose private keys you want to traverse.
 
1748
 *      callback
 
1749
 *          A callback function that will be called for each key.
 
1750
 *      arg
 
1751
 *          An argument that will be passed to the callback function.
 
1752
 */
 
1753
SECStatus
 
1754
PK11_TraversePrivateKeysInSlot( PK11SlotInfo *slot,
 
1755
    SECStatus(* callback)(SECKEYPrivateKey*, void*), void *arg)
 
1756
{
 
1757
    pk11KeyCallback perKeyCB;
 
1758
    pk11TraverseSlot perObjectCB;
 
1759
    CK_OBJECT_CLASS privkClass = CKO_PRIVATE_KEY;
 
1760
    CK_BBOOL ckTrue = CK_TRUE;
 
1761
    CK_ATTRIBUTE theTemplate[2];
 
1762
    int templateSize = 2;
 
1763
 
 
1764
    theTemplate[0].type = CKA_CLASS;
 
1765
    theTemplate[0].pValue = &privkClass;
 
1766
    theTemplate[0].ulValueLen = sizeof(privkClass);
 
1767
    theTemplate[1].type = CKA_TOKEN;
 
1768
    theTemplate[1].pValue = &ckTrue;
 
1769
    theTemplate[1].ulValueLen = sizeof(ckTrue);
 
1770
 
 
1771
    if(slot==NULL) {
 
1772
        return SECSuccess;
 
1773
    }
 
1774
 
 
1775
    perObjectCB.callback = pk11_DoKeys;
 
1776
    perObjectCB.callbackArg = &perKeyCB;
 
1777
    perObjectCB.findTemplate = theTemplate;
 
1778
    perObjectCB.templateCount = templateSize;
 
1779
    perKeyCB.callback = callback;
 
1780
    perKeyCB.callbackArg = arg;
 
1781
    perKeyCB.wincx = NULL;
 
1782
 
 
1783
    return PK11_TraverseSlot(slot, &perObjectCB);
 
1784
}
 
1785
 
 
1786
/*
 
1787
 * return the private key with the given ID
 
1788
 */
 
1789
CK_OBJECT_HANDLE
 
1790
pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)
 
1791
{
 
1792
    CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
 
1793
    CK_ATTRIBUTE theTemplate[] = {
 
1794
        { CKA_ID, NULL, 0 },
 
1795
        { CKA_CLASS, NULL, 0 },
 
1796
    };
 
1797
    /* if you change the array, change the variable below as well */
 
1798
    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
 
1799
    CK_ATTRIBUTE *attrs = theTemplate;
 
1800
 
 
1801
    PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++;
 
1802
    PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
 
1803
 
 
1804
    return pk11_FindObjectByTemplate(slot,theTemplate,tsize);
 
1805
 
1806
 
 
1807
 
 
1808
SECKEYPrivateKey *
 
1809
PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
 
1810
{
 
1811
    CK_OBJECT_HANDLE keyHandle;
 
1812
    SECKEYPrivateKey *privKey;
 
1813
 
 
1814
    keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
 
1815
    if (keyHandle == CK_INVALID_HANDLE) { 
 
1816
        return NULL;
 
1817
    }
 
1818
    privKey =  PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
 
1819
    return privKey;
 
1820
}
 
1821
 
 
1822
/*
 
1823
 * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
 
1824
 * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
 
1825
 * smart cards happy.
 
1826
 */
 
1827
SECItem *
 
1828
PK11_MakeIDFromPubKey(SECItem *pubKeyData) 
 
1829
{
 
1830
    PK11Context *context;
 
1831
    SECItem *certCKA_ID;
 
1832
    SECStatus rv;
 
1833
 
 
1834
    context = PK11_CreateDigestContext(SEC_OID_SHA1);
 
1835
    if (context == NULL) {
 
1836
        return NULL;
 
1837
    }
 
1838
 
 
1839
    rv = PK11_DigestBegin(context);
 
1840
    if (rv == SECSuccess) {
 
1841
        rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len);
 
1842
    }
 
1843
    if (rv != SECSuccess) {
 
1844
        PK11_DestroyContext(context,PR_TRUE);
 
1845
        return NULL;
 
1846
    }
 
1847
 
 
1848
    certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
 
1849
    if (certCKA_ID == NULL) {
 
1850
        PK11_DestroyContext(context,PR_TRUE);
 
1851
        return NULL;
 
1852
    }
 
1853
 
 
1854
    certCKA_ID->len = SHA1_LENGTH;
 
1855
    certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len);
 
1856
    if (certCKA_ID->data == NULL) {
 
1857
        PORT_Free(certCKA_ID);
 
1858
        PK11_DestroyContext(context,PR_TRUE);
 
1859
        return NULL;
 
1860
    }
 
1861
 
 
1862
    rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len,
 
1863
                                                                SHA1_LENGTH);
 
1864
    PK11_DestroyContext(context,PR_TRUE);
 
1865
    if (rv != SECSuccess) {
 
1866
        SECITEM_FreeItem(certCKA_ID,PR_TRUE);
 
1867
        return NULL;
 
1868
    }
 
1869
 
 
1870
    return certCKA_ID;
 
1871
}
 
1872
 
 
1873
SECItem *
 
1874
PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx)
 
1875
{
 
1876
    CK_ATTRIBUTE theTemplate[] = {
 
1877
        { CKA_ID, NULL, 0 },
 
1878
    };
 
1879
    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
 
1880
    SECItem *item = NULL;
 
1881
    CK_RV crv;
 
1882
 
 
1883
    crv = PK11_GetAttributes(NULL,key->pkcs11Slot,key->pkcs11ID,
 
1884
                                                        theTemplate,tsize);
 
1885
    if (crv != CKR_OK) {
 
1886
        PORT_SetError( PK11_MapError(crv) );
 
1887
        goto loser;
 
1888
    }
 
1889
 
 
1890
    item = PORT_ZNew(SECItem);
 
1891
    if (item) {
 
1892
        item->data = (unsigned char*) theTemplate[0].pValue;
 
1893
        item->len = theTemplate[0].ulValueLen;
 
1894
    }
 
1895
 
 
1896
loser:
 
1897
    return item;
 
1898
}
 
1899
 
 
1900
SECItem *
 
1901
PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *privKey)
 
1902
{
 
1903
    return pk11_GetLowLevelKeyFromHandle(privKey->pkcs11Slot,privKey->pkcs11ID);
 
1904
}
 
1905
 
 
1906
static SECStatus
 
1907
privateKeyListCallback(SECKEYPrivateKey *key, void *arg)
 
1908
{
 
1909
    SECKEYPrivateKeyList *list = (SECKEYPrivateKeyList*)arg;
 
1910
    return SECKEY_AddPrivateKeyToListTail(list, SECKEY_CopyPrivateKey(key));
 
1911
}
 
1912
 
 
1913
SECKEYPrivateKeyList*
 
1914
PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot)
 
1915
{
 
1916
    SECStatus status;
 
1917
    SECKEYPrivateKeyList *keys;
 
1918
 
 
1919
    keys = SECKEY_NewPrivateKeyList();
 
1920
    if(keys == NULL) return NULL;
 
1921
 
 
1922
    status = PK11_TraversePrivateKeysInSlot(slot, privateKeyListCallback,
 
1923
                (void*)keys);
 
1924
 
 
1925
    if( status != SECSuccess ) {
 
1926
        SECKEY_DestroyPrivateKeyList(keys);
 
1927
        keys = NULL;
 
1928
    }
 
1929
 
 
1930
    return keys;
 
1931
}
 
1932
 
 
1933
SECKEYPublicKeyList*
 
1934
PK11_ListPublicKeysInSlot(PK11SlotInfo *slot, char *nickname)
 
1935
{
 
1936
    CK_ATTRIBUTE findTemp[4];
 
1937
    CK_ATTRIBUTE *attrs;
 
1938
    CK_BBOOL ckTrue = CK_TRUE;
 
1939
    CK_OBJECT_CLASS keyclass = CKO_PUBLIC_KEY;
 
1940
    int tsize = 0;
 
1941
    int objCount = 0;
 
1942
    CK_OBJECT_HANDLE *key_ids;
 
1943
    SECKEYPublicKeyList *keys;
 
1944
    int i,len;
 
1945
 
 
1946
 
 
1947
    attrs = findTemp;
 
1948
    PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
 
1949
    PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
 
1950
    if (nickname) {
 
1951
        len = PORT_Strlen(nickname)-1;
 
1952
        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
 
1953
    }
 
1954
    tsize = attrs - findTemp;
 
1955
    PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
 
1956
 
 
1957
    key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
 
1958
    if (key_ids == NULL) {
 
1959
        return NULL;
 
1960
    }
 
1961
    keys = SECKEY_NewPublicKeyList();
 
1962
    if (keys == NULL) {
 
1963
        PORT_Free(key_ids);
 
1964
        return NULL;
 
1965
    }
 
1966
 
 
1967
    for (i=0; i < objCount ; i++) {
 
1968
        SECKEYPublicKey *pubKey = 
 
1969
                                PK11_ExtractPublicKey(slot,nullKey,key_ids[i]);
 
1970
        if (pubKey) {
 
1971
            SECKEY_AddPublicKeyToListTail(keys, pubKey);
 
1972
        }
 
1973
   }
 
1974
 
 
1975
   PORT_Free(key_ids);
 
1976
   return keys;
 
1977
}
 
1978
 
 
1979
SECKEYPrivateKeyList*
 
1980
PK11_ListPrivKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx)
 
1981
{
 
1982
    CK_ATTRIBUTE findTemp[4];
 
1983
    CK_ATTRIBUTE *attrs;
 
1984
    CK_BBOOL ckTrue = CK_TRUE;
 
1985
    CK_OBJECT_CLASS keyclass = CKO_PRIVATE_KEY;
 
1986
    int tsize = 0;
 
1987
    int objCount = 0;
 
1988
    CK_OBJECT_HANDLE *key_ids;
 
1989
    SECKEYPrivateKeyList *keys;
 
1990
    int i,len;
 
1991
 
 
1992
 
 
1993
    attrs = findTemp;
 
1994
    PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++;
 
1995
    PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++;
 
1996
    if (nickname) {
 
1997
        len = PORT_Strlen(nickname)-1;
 
1998
        PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++;
 
1999
    }
 
2000
    tsize = attrs - findTemp;
 
2001
    PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE));
 
2002
 
 
2003
    key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount);
 
2004
    if (key_ids == NULL) {
 
2005
        return NULL;
 
2006
    }
 
2007
    keys = SECKEY_NewPrivateKeyList();
 
2008
    if (keys == NULL) {
 
2009
        PORT_Free(key_ids);
 
2010
        return NULL;
 
2011
    }
 
2012
 
 
2013
    for (i=0; i < objCount ; i++) {
 
2014
        SECKEYPrivateKey *privKey = 
 
2015
                PK11_MakePrivKey(slot,nullKey,PR_TRUE,key_ids[i],wincx);
 
2016
        SECKEY_AddPrivateKeyToListTail(keys, privKey);
 
2017
   }
 
2018
 
 
2019
   PORT_Free(key_ids);
 
2020
   return keys;
 
2021
}
 
2022