~ubuntu-branches/ubuntu/quantal/nss/quantal-updates

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/dev/devtoken.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-11-14 14:58:07 UTC
  • mfrom: (1.1.19)
  • Revision ID: package-import@ubuntu.com-20131114145807-vj6v4erz8xj6kwz3
Tags: 3.15.3-0ubuntu0.12.10.1
* SECURITY UPDATE: New upstream release to fix multiple security issues
  and add TLSv1.2 support.
  - CVE-2013-1739
  - CVE-2013-1741
  - CVE-2013-5605
  - CVE-2013-5606
* Adjusted packaging for 3.15.3:
  - debian/patches/*: refreshed.
  - debian/patches/lower-dhe-priority.patch: removed, no longer needed,
    was a workaround for an old version of firefox.
  - debian/libnss3.symbols: added new symbols.
  - debian/rules: updated for new source layout.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
 
 
5
 
#ifdef DEBUG
6
 
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.57 $ $Date: 2012/04/25 14:49:42 $";
7
 
#endif /* DEBUG */
8
 
 
9
 
#include "pkcs11.h"
10
 
 
11
 
#ifndef DEVM_H
12
 
#include "devm.h"
13
 
#endif /* DEVM_H */
14
 
 
15
 
#ifndef CKHELPER_H
16
 
#include "ckhelper.h"
17
 
#endif /* CKHELPER_H */
18
 
 
19
 
#include "pk11func.h"
20
 
#include "dev3hack.h"
21
 
#include "secerr.h"
22
 
 
23
 
extern const NSSError NSS_ERROR_NOT_FOUND;
24
 
extern const NSSError NSS_ERROR_INVALID_ARGUMENT;
25
 
extern const NSSError NSS_ERROR_PKCS11;
26
 
 
27
 
/* The number of object handles to grab during each call to C_FindObjects */
28
 
#define OBJECT_STACK_SIZE 16
29
 
 
30
 
NSS_IMPLEMENT PRStatus
31
 
nssToken_Destroy (
32
 
  NSSToken *tok
33
 
)
34
 
{
35
 
    if (tok) {
36
 
        if (PR_ATOMIC_DECREMENT(&tok->base.refCount) == 0) {
37
 
            PZ_DestroyLock(tok->base.lock);
38
 
            nssTokenObjectCache_Destroy(tok->cache);
39
 
            /* The token holds the first/last reference to the slot.
40
 
             * When the token is actually destroyed, that ref must go too.
41
 
             */
42
 
            (void)nssSlot_Destroy(tok->slot);
43
 
            return nssArena_Destroy(tok->base.arena);
44
 
        }
45
 
    }
46
 
    return PR_SUCCESS;
47
 
}
48
 
 
49
 
NSS_IMPLEMENT void
50
 
nssToken_Remove (
51
 
  NSSToken *tok
52
 
)
53
 
{
54
 
    nssTokenObjectCache_Clear(tok->cache);
55
 
}
56
 
 
57
 
NSS_IMPLEMENT void
58
 
NSSToken_Destroy (
59
 
  NSSToken *tok
60
 
)
61
 
{
62
 
    (void)nssToken_Destroy(tok);
63
 
}
64
 
 
65
 
NSS_IMPLEMENT NSSToken *
66
 
nssToken_AddRef (
67
 
  NSSToken *tok
68
 
)
69
 
{
70
 
    PR_ATOMIC_INCREMENT(&tok->base.refCount);
71
 
    return tok;
72
 
}
73
 
 
74
 
NSS_IMPLEMENT NSSSlot *
75
 
nssToken_GetSlot (
76
 
  NSSToken *tok
77
 
)
78
 
{
79
 
    return nssSlot_AddRef(tok->slot);
80
 
}
81
 
 
82
 
NSS_IMPLEMENT void *
83
 
nssToken_GetCryptokiEPV (
84
 
  NSSToken *token
85
 
)
86
 
{
87
 
    return nssSlot_GetCryptokiEPV(token->slot);
88
 
}
89
 
 
90
 
NSS_IMPLEMENT nssSession *
91
 
nssToken_GetDefaultSession (
92
 
  NSSToken *token
93
 
)
94
 
{
95
 
    return token->defaultSession;
96
 
}
97
 
 
98
 
NSS_IMPLEMENT NSSUTF8 *
99
 
nssToken_GetName (
100
 
  NSSToken *tok
101
 
)
102
 
{
103
 
    if (tok == NULL) {
104
 
        return "";
105
 
    }
106
 
    if (tok->base.name[0] == 0) {
107
 
        (void) nssSlot_IsTokenPresent(tok->slot);
108
 
    } 
109
 
    return tok->base.name;
110
 
}
111
 
 
112
 
NSS_IMPLEMENT NSSUTF8 *
113
 
NSSToken_GetName (
114
 
  NSSToken *token
115
 
)
116
 
{
117
 
    return nssToken_GetName(token);
118
 
}
119
 
 
120
 
NSS_IMPLEMENT PRBool
121
 
nssToken_IsLoginRequired (
122
 
  NSSToken *token
123
 
)
124
 
{
125
 
    return (token->ckFlags & CKF_LOGIN_REQUIRED);
126
 
}
127
 
 
128
 
NSS_IMPLEMENT PRBool
129
 
nssToken_NeedsPINInitialization (
130
 
  NSSToken *token
131
 
)
132
 
{
133
 
    return (!(token->ckFlags & CKF_USER_PIN_INITIALIZED));
134
 
}
135
 
 
136
 
NSS_IMPLEMENT PRStatus
137
 
nssToken_DeleteStoredObject (
138
 
  nssCryptokiObject *instance
139
 
)
140
 
{
141
 
    CK_RV ckrv;
142
 
    PRStatus status;
143
 
    PRBool createdSession = PR_FALSE;
144
 
    NSSToken *token = instance->token;
145
 
    nssSession *session = NULL;
146
 
    void *epv = nssToken_GetCryptokiEPV(instance->token);
147
 
    if (token->cache) {
148
 
        nssTokenObjectCache_RemoveObject(token->cache, instance);
149
 
    }
150
 
    if (instance->isTokenObject) {
151
 
       if (token->defaultSession && 
152
 
           nssSession_IsReadWrite(token->defaultSession)) {
153
 
           session = token->defaultSession;
154
 
       } else {
155
 
           session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
156
 
           createdSession = PR_TRUE;
157
 
       }
158
 
    }
159
 
    if (session == NULL) {
160
 
        return PR_FAILURE;
161
 
    }
162
 
    nssSession_EnterMonitor(session);
163
 
    ckrv = CKAPI(epv)->C_DestroyObject(session->handle, instance->handle);
164
 
    nssSession_ExitMonitor(session);
165
 
    if (createdSession) {
166
 
        nssSession_Destroy(session);
167
 
    }
168
 
    status = PR_SUCCESS;
169
 
    if (ckrv != CKR_OK) {
170
 
        status = PR_FAILURE;
171
 
        /* use the error stack to pass the PKCS #11 error out  */
172
 
        nss_SetError(ckrv);
173
 
        nss_SetError(NSS_ERROR_PKCS11);
174
 
    }
175
 
    return status;
176
 
}
177
 
 
178
 
static nssCryptokiObject *
179
 
import_object (
180
 
  NSSToken *tok,
181
 
  nssSession *sessionOpt,
182
 
  CK_ATTRIBUTE_PTR objectTemplate,
183
 
  CK_ULONG otsize
184
 
)
185
 
{
186
 
    nssSession *session = NULL;
187
 
    PRBool createdSession = PR_FALSE;
188
 
    nssCryptokiObject *object = NULL;
189
 
    CK_OBJECT_HANDLE handle;
190
 
    CK_RV ckrv;
191
 
    void *epv = nssToken_GetCryptokiEPV(tok);
192
 
    if (nssCKObject_IsTokenObjectTemplate(objectTemplate, otsize)) {
193
 
        if (sessionOpt) {
194
 
            if (!nssSession_IsReadWrite(sessionOpt)) {
195
 
                nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
196
 
                return NULL;
197
 
            }
198
 
            session = sessionOpt;
199
 
        } else if (tok->defaultSession && 
200
 
                   nssSession_IsReadWrite(tok->defaultSession)) {
201
 
            session = tok->defaultSession;
202
 
        } else {
203
 
            session = nssSlot_CreateSession(tok->slot, NULL, PR_TRUE);
204
 
            createdSession = PR_TRUE;
205
 
        }
206
 
    } else {
207
 
        session = (sessionOpt) ? sessionOpt : tok->defaultSession;
208
 
    }
209
 
    if (session == NULL) {
210
 
        nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
211
 
        return NULL;
212
 
    }
213
 
    nssSession_EnterMonitor(session);
214
 
    ckrv = CKAPI(epv)->C_CreateObject(session->handle, 
215
 
                                      objectTemplate, otsize,
216
 
                                      &handle);
217
 
    nssSession_ExitMonitor(session);
218
 
    if (ckrv == CKR_OK) {
219
 
        object = nssCryptokiObject_Create(tok, session, handle);
220
 
    } else {
221
 
        nss_SetError(ckrv);
222
 
        nss_SetError(NSS_ERROR_PKCS11);
223
 
    }
224
 
    if (createdSession) {
225
 
        nssSession_Destroy(session);
226
 
    }
227
 
    return object;
228
 
}
229
 
 
230
 
static nssCryptokiObject **
231
 
create_objects_from_handles (
232
 
  NSSToken *tok,
233
 
  nssSession *session,
234
 
  CK_OBJECT_HANDLE *handles,
235
 
  PRUint32 numH
236
 
)
237
 
{
238
 
    nssCryptokiObject **objects;
239
 
    objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numH + 1);
240
 
    if (objects) {
241
 
        PRInt32 i;
242
 
        for (i=0; i<(PRInt32)numH; i++) {
243
 
            objects[i] = nssCryptokiObject_Create(tok, session, handles[i]);
244
 
            if (!objects[i]) {
245
 
                for (--i; i>0; --i) {
246
 
                    nssCryptokiObject_Destroy(objects[i]);
247
 
                }
248
 
                nss_ZFreeIf(objects);
249
 
                objects = NULL;
250
 
                break;
251
 
            }
252
 
        }
253
 
    }
254
 
    return objects;
255
 
}
256
 
 
257
 
static nssCryptokiObject **
258
 
find_objects (
259
 
  NSSToken *tok,
260
 
  nssSession *sessionOpt,
261
 
  CK_ATTRIBUTE_PTR obj_template,
262
 
  CK_ULONG otsize,
263
 
  PRUint32 maximumOpt,
264
 
  PRStatus *statusOpt
265
 
)
266
 
{
267
 
    CK_RV ckrv = CKR_OK;
268
 
    CK_ULONG count;
269
 
    CK_OBJECT_HANDLE *objectHandles = NULL;
270
 
    CK_OBJECT_HANDLE staticObjects[OBJECT_STACK_SIZE];
271
 
    PRUint32 arraySize, numHandles;
272
 
    void *epv = nssToken_GetCryptokiEPV(tok);
273
 
    nssCryptokiObject **objects;
274
 
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
275
 
 
276
 
    /* Don't ask the module to use an invalid session handle. */
277
 
    if (!session || session->handle == CK_INVALID_SESSION) {
278
 
        ckrv = CKR_SESSION_HANDLE_INVALID;
279
 
        goto loser;                
280
 
    }
281
 
 
282
 
    /* the arena is only for the array of object handles */
283
 
    if (maximumOpt > 0) {
284
 
        arraySize = maximumOpt;
285
 
    } else {
286
 
        arraySize = OBJECT_STACK_SIZE;
287
 
    }
288
 
    numHandles = 0;
289
 
    if (arraySize <= OBJECT_STACK_SIZE) {
290
 
        objectHandles = staticObjects;
291
 
    } else {
292
 
        objectHandles = nss_ZNEWARRAY(NULL, CK_OBJECT_HANDLE, arraySize);
293
 
    }
294
 
    if (!objectHandles) {
295
 
        ckrv = CKR_HOST_MEMORY;
296
 
        goto loser;
297
 
    }
298
 
    nssSession_EnterMonitor(session); /* ==== session lock === */
299
 
    /* Initialize the find with the template */
300
 
    ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, 
301
 
                                         obj_template, otsize);
302
 
    if (ckrv != CKR_OK) {
303
 
        nssSession_ExitMonitor(session);
304
 
        goto loser;
305
 
    }
306
 
    while (PR_TRUE) {
307
 
        /* Issue the find for up to arraySize - numHandles objects */
308
 
        ckrv = CKAPI(epv)->C_FindObjects(session->handle, 
309
 
                                         objectHandles + numHandles, 
310
 
                                         arraySize - numHandles, 
311
 
                                         &count);
312
 
        if (ckrv != CKR_OK) {
313
 
            nssSession_ExitMonitor(session);
314
 
            goto loser;
315
 
        }
316
 
        /* bump the number of found objects */
317
 
        numHandles += count;
318
 
        if (maximumOpt > 0 || numHandles < arraySize) {
319
 
            /* When a maximum is provided, the search is done all at once,
320
 
             * so the search is finished.  If the number returned was less 
321
 
             * than the number sought, the search is finished.
322
 
             */
323
 
            break;
324
 
        }
325
 
        /* the array is filled, double it and continue */
326
 
        arraySize *= 2;
327
 
        if (objectHandles == staticObjects) {
328
 
            objectHandles = nss_ZNEWARRAY(NULL,CK_OBJECT_HANDLE, arraySize);
329
 
            if (objectHandles) {
330
 
                PORT_Memcpy(objectHandles, staticObjects, 
331
 
                        OBJECT_STACK_SIZE * sizeof(objectHandles[1]));
332
 
            }
333
 
        } else {
334
 
            objectHandles = nss_ZREALLOCARRAY(objectHandles, 
335
 
                                          CK_OBJECT_HANDLE, 
336
 
                                          arraySize);
337
 
        }
338
 
        if (!objectHandles) {
339
 
            nssSession_ExitMonitor(session);
340
 
            ckrv = CKR_HOST_MEMORY;
341
 
            goto loser;
342
 
        }
343
 
    }
344
 
    ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
345
 
    nssSession_ExitMonitor(session); /* ==== end session lock === */
346
 
    if (ckrv != CKR_OK) {
347
 
        goto loser;
348
 
    }
349
 
    if (numHandles > 0) {
350
 
        objects = create_objects_from_handles(tok, session,
351
 
                                              objectHandles, numHandles);
352
 
    } else {
353
 
        nss_SetError(NSS_ERROR_NOT_FOUND);
354
 
        objects = NULL;
355
 
    }
356
 
    if (objectHandles && objectHandles != staticObjects) {
357
 
        nss_ZFreeIf(objectHandles);
358
 
    }
359
 
    if (statusOpt) *statusOpt = PR_SUCCESS;
360
 
    return objects;
361
 
loser:
362
 
    if (objectHandles && objectHandles != staticObjects) {
363
 
        nss_ZFreeIf(objectHandles);
364
 
    }
365
 
    /*
366
 
     * These errors should be treated the same as if the objects just weren't
367
 
     * found..
368
 
     */
369
 
    if ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
370
 
        (ckrv == CKR_ATTRIBUTE_VALUE_INVALID) ||
371
 
        (ckrv == CKR_DATA_INVALID) ||
372
 
        (ckrv == CKR_DATA_LEN_RANGE) ||
373
 
        (ckrv == CKR_FUNCTION_NOT_SUPPORTED) ||
374
 
        (ckrv == CKR_TEMPLATE_INCOMPLETE) ||
375
 
        (ckrv == CKR_TEMPLATE_INCONSISTENT)) {
376
 
 
377
 
        nss_SetError(NSS_ERROR_NOT_FOUND);
378
 
        if (statusOpt) *statusOpt = PR_SUCCESS;
379
 
    } else {
380
 
        nss_SetError(ckrv);
381
 
        nss_SetError(NSS_ERROR_PKCS11);
382
 
        if (statusOpt) *statusOpt = PR_FAILURE;
383
 
    }
384
 
    return (nssCryptokiObject **)NULL;
385
 
}
386
 
 
387
 
static nssCryptokiObject **
388
 
find_objects_by_template (
389
 
  NSSToken *token,
390
 
  nssSession *sessionOpt,
391
 
  CK_ATTRIBUTE_PTR obj_template,
392
 
  CK_ULONG otsize,
393
 
  PRUint32 maximumOpt,
394
 
  PRStatus *statusOpt
395
 
)
396
 
{
397
 
    CK_OBJECT_CLASS objclass = (CK_OBJECT_CLASS)-1;
398
 
    nssCryptokiObject **objects = NULL;
399
 
    PRUint32 i;
400
 
 
401
 
    if (!token) {
402
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
403
 
        if (statusOpt) 
404
 
            *statusOpt = PR_FAILURE;
405
 
        return NULL;
406
 
    }
407
 
    for (i=0; i<otsize; i++) {
408
 
        if (obj_template[i].type == CKA_CLASS) {
409
 
            objclass = *(CK_OBJECT_CLASS *)obj_template[i].pValue;
410
 
            break;
411
 
        }
412
 
    }
413
 
    PR_ASSERT(i < otsize);
414
 
    if (i == otsize) {
415
 
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
416
 
        if (statusOpt) *statusOpt = PR_FAILURE;
417
 
        return NULL;
418
 
    }
419
 
    /* If these objects are being cached, try looking there first */
420
 
    if (token->cache && 
421
 
        nssTokenObjectCache_HaveObjectClass(token->cache, objclass)) 
422
 
    {
423
 
        PRStatus status;
424
 
        objects = nssTokenObjectCache_FindObjectsByTemplate(token->cache,
425
 
                                                            objclass,
426
 
                                                            obj_template,
427
 
                                                            otsize,
428
 
                                                            maximumOpt,
429
 
                                                            &status);
430
 
        if (status == PR_SUCCESS) {
431
 
            if (statusOpt) *statusOpt = status;
432
 
            return objects;
433
 
        }
434
 
    }
435
 
    /* Either they are not cached, or cache failed; look on token. */
436
 
    objects = find_objects(token, sessionOpt, 
437
 
                           obj_template, otsize, 
438
 
                           maximumOpt, statusOpt);
439
 
    return objects;
440
 
}
441
 
 
442
 
extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
443
 
 
444
 
NSS_IMPLEMENT nssCryptokiObject *
445
 
nssToken_ImportCertificate (
446
 
  NSSToken *tok,
447
 
  nssSession *sessionOpt,
448
 
  NSSCertificateType certType,
449
 
  NSSItem *id,
450
 
  const NSSUTF8 *nickname,
451
 
  NSSDER *encoding,
452
 
  NSSDER *issuer,
453
 
  NSSDER *subject,
454
 
  NSSDER *serial,
455
 
  NSSASCII7 *email,
456
 
  PRBool asTokenObject
457
 
)
458
 
{
459
 
    PRStatus status;
460
 
    CK_CERTIFICATE_TYPE cert_type;
461
 
    CK_ATTRIBUTE_PTR attr;
462
 
    CK_ATTRIBUTE cert_tmpl[10];
463
 
    CK_ULONG ctsize;
464
 
    nssTokenSearchType searchType;
465
 
    nssCryptokiObject *rvObject = NULL;
466
 
 
467
 
    if (!tok) {
468
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
469
 
        return NULL;
470
 
    }
471
 
    if (certType == NSSCertificateType_PKIX) {
472
 
        cert_type = CKC_X_509;
473
 
    } else {
474
 
        return (nssCryptokiObject *)NULL;
475
 
    }
476
 
    NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
477
 
    if (asTokenObject) {
478
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
479
 
        searchType = nssTokenSearchType_TokenOnly;
480
 
    } else {
481
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
482
 
        searchType = nssTokenSearchType_SessionOnly;
483
 
    }
484
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS,            &g_ck_class_cert);
485
 
    NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CERTIFICATE_TYPE,  cert_type);
486
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID,                id);
487
 
    NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL,             nickname);
488
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE,             encoding);
489
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER,            issuer);
490
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT,           subject);
491
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER,     serial);
492
 
    if (email) {
493
 
        NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL,    email);
494
 
    }
495
 
    NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
496
 
    /* see if the cert is already there */
497
 
    rvObject = nssToken_FindCertificateByIssuerAndSerialNumber(tok,
498
 
                                                               sessionOpt,
499
 
                                                               issuer,
500
 
                                                               serial,
501
 
                                                               searchType,
502
 
                                                               NULL);
503
 
    if (rvObject) {
504
 
        NSSItem existingDER;
505
 
        NSSSlot *slot = nssToken_GetSlot(tok);
506
 
        nssSession *session = nssSlot_CreateSession(slot, NULL, PR_TRUE);
507
 
        if (!session) {
508
 
            nssCryptokiObject_Destroy(rvObject);
509
 
            nssSlot_Destroy(slot);
510
 
            return (nssCryptokiObject *)NULL;
511
 
        }
512
 
        /* Reject any attempt to import a new cert that has the same
513
 
         * issuer/serial as an existing cert, but does not have the
514
 
         * same encoding
515
 
         */
516
 
        NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
517
 
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
518
 
        NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
519
 
        status = nssCKObject_GetAttributes(rvObject->handle, 
520
 
                                           cert_tmpl, ctsize, NULL,
521
 
                                           session, slot);
522
 
        NSS_CK_ATTRIBUTE_TO_ITEM(cert_tmpl, &existingDER);
523
 
        if (status == PR_SUCCESS) {
524
 
            if (!nssItem_Equal(encoding, &existingDER, NULL)) {
525
 
                nss_SetError(NSS_ERROR_INVALID_CERTIFICATE);
526
 
                status = PR_FAILURE;
527
 
            }
528
 
            nss_ZFreeIf(existingDER.data);
529
 
        }
530
 
        if (status == PR_FAILURE) {
531
 
            nssCryptokiObject_Destroy(rvObject);
532
 
            nssSession_Destroy(session);
533
 
            nssSlot_Destroy(slot);
534
 
            return (nssCryptokiObject *)NULL;
535
 
        }
536
 
        /* according to PKCS#11, label, ID, issuer, and serial number 
537
 
         * may change after the object has been created.  For PKIX, the
538
 
         * last two attributes can't change, so for now we'll only worry
539
 
         * about the first two.
540
 
         */
541
 
        NSS_CK_TEMPLATE_START(cert_tmpl, attr, ctsize);
542
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID,    id);
543
 
        NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
544
 
        NSS_CK_TEMPLATE_FINISH(cert_tmpl, attr, ctsize);
545
 
        /* reset the mutable attributes on the token */
546
 
        nssCKObject_SetAttributes(rvObject->handle, 
547
 
                                  cert_tmpl, ctsize,
548
 
                                  session, slot);
549
 
        if (!rvObject->label && nickname) {
550
 
            rvObject->label = nssUTF8_Duplicate(nickname, NULL);
551
 
        }
552
 
        nssSession_Destroy(session);
553
 
        nssSlot_Destroy(slot);
554
 
    } else {
555
 
        /* Import the certificate onto the token */
556
 
        rvObject = import_object(tok, sessionOpt, cert_tmpl, ctsize);
557
 
    }
558
 
    if (rvObject && tok->cache) {
559
 
        /* The cache will overwrite the attributes if the object already
560
 
         * exists.
561
 
         */
562
 
        nssTokenObjectCache_ImportObject(tok->cache, rvObject,
563
 
                                         CKO_CERTIFICATE,
564
 
                                         cert_tmpl, ctsize);
565
 
    }
566
 
    return rvObject;
567
 
}
568
 
 
569
 
/* traverse all objects of the given class - this should only happen
570
 
 * if the token has been marked as "traversable"
571
 
 */
572
 
NSS_IMPLEMENT nssCryptokiObject **
573
 
nssToken_FindObjects (
574
 
  NSSToken *token,
575
 
  nssSession *sessionOpt,
576
 
  CK_OBJECT_CLASS objclass,
577
 
  nssTokenSearchType searchType,
578
 
  PRUint32 maximumOpt,
579
 
  PRStatus *statusOpt
580
 
)
581
 
{
582
 
    CK_ATTRIBUTE_PTR attr;
583
 
    CK_ATTRIBUTE obj_template[2];
584
 
    CK_ULONG obj_size;
585
 
    nssCryptokiObject **objects;
586
 
    NSS_CK_TEMPLATE_START(obj_template, attr, obj_size);
587
 
    /* Set the search to token/session only if provided */
588
 
    if (searchType == nssTokenSearchType_SessionOnly) {
589
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
590
 
    } else if (searchType == nssTokenSearchType_TokenOnly ||
591
 
               searchType == nssTokenSearchType_TokenForced) {
592
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
593
 
    }
594
 
    NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, objclass);
595
 
    NSS_CK_TEMPLATE_FINISH(obj_template, attr, obj_size);
596
 
 
597
 
    if (searchType == nssTokenSearchType_TokenForced) {
598
 
        objects = find_objects(token, sessionOpt,
599
 
                               obj_template, obj_size,
600
 
                               maximumOpt, statusOpt);
601
 
    } else {
602
 
        objects = find_objects_by_template(token, sessionOpt,
603
 
                                           obj_template, obj_size,
604
 
                                           maximumOpt, statusOpt);
605
 
    }
606
 
    return objects;
607
 
}
608
 
 
609
 
NSS_IMPLEMENT nssCryptokiObject **
610
 
nssToken_FindCertificatesBySubject (
611
 
  NSSToken *token,
612
 
  nssSession *sessionOpt,
613
 
  NSSDER *subject,
614
 
  nssTokenSearchType searchType,
615
 
  PRUint32 maximumOpt,
616
 
  PRStatus *statusOpt
617
 
)
618
 
{
619
 
    CK_ATTRIBUTE_PTR attr;
620
 
    CK_ATTRIBUTE subj_template[3];
621
 
    CK_ULONG stsize;
622
 
    nssCryptokiObject **objects;
623
 
    NSS_CK_TEMPLATE_START(subj_template, attr, stsize);
624
 
    /* Set the search to token/session only if provided */
625
 
    if (searchType == nssTokenSearchType_SessionOnly) {
626
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
627
 
    } else if (searchType == nssTokenSearchType_TokenOnly) {
628
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
629
 
    }
630
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
631
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
632
 
    NSS_CK_TEMPLATE_FINISH(subj_template, attr, stsize);
633
 
    /* now locate the token certs matching this template */
634
 
    objects = find_objects_by_template(token, sessionOpt,
635
 
                                       subj_template, stsize,
636
 
                                       maximumOpt, statusOpt);
637
 
    return objects;
638
 
}
639
 
 
640
 
NSS_IMPLEMENT nssCryptokiObject **
641
 
nssToken_FindCertificatesByNickname (
642
 
  NSSToken *token,
643
 
  nssSession *sessionOpt,
644
 
  const NSSUTF8 *name,
645
 
  nssTokenSearchType searchType,
646
 
  PRUint32 maximumOpt,
647
 
  PRStatus *statusOpt
648
 
)
649
 
{
650
 
    CK_ATTRIBUTE_PTR attr;
651
 
    CK_ATTRIBUTE nick_template[3];
652
 
    CK_ULONG ntsize;
653
 
    nssCryptokiObject **objects;
654
 
    NSS_CK_TEMPLATE_START(nick_template, attr, ntsize);
655
 
    NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, name);
656
 
    /* Set the search to token/session only if provided */
657
 
    if (searchType == nssTokenSearchType_SessionOnly) {
658
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
659
 
    } else if (searchType == nssTokenSearchType_TokenOnly) {
660
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
661
 
    }
662
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
663
 
    NSS_CK_TEMPLATE_FINISH(nick_template, attr, ntsize);
664
 
    /* now locate the token certs matching this template */
665
 
    objects = find_objects_by_template(token, sessionOpt,
666
 
                                       nick_template, ntsize, 
667
 
                                       maximumOpt, statusOpt);
668
 
    if (!objects) {
669
 
        /* This is to workaround the fact that PKCS#11 doesn't specify
670
 
         * whether the '\0' should be included.  XXX Is that still true?
671
 
         * im - this is not needed by the current softoken.  However, I'm 
672
 
         * leaving it in until I have surveyed more tokens to see if it needed.
673
 
         * well, its needed by the builtin token...
674
 
         */
675
 
        nick_template[0].ulValueLen++;
676
 
        objects = find_objects_by_template(token, sessionOpt,
677
 
                                           nick_template, ntsize, 
678
 
                                           maximumOpt, statusOpt);
679
 
    }
680
 
    return objects;
681
 
}
682
 
 
683
 
/* XXX
684
 
 * This function *does not* use the token object cache, because not even
685
 
 * the softoken will return a value for CKA_NSS_EMAIL from a call
686
 
 * to GetAttributes.  The softoken does allow searches with that attribute,
687
 
 * it just won't return a value for it.
688
 
 */
689
 
NSS_IMPLEMENT nssCryptokiObject **
690
 
nssToken_FindCertificatesByEmail (
691
 
  NSSToken *token,
692
 
  nssSession *sessionOpt,
693
 
  NSSASCII7 *email,
694
 
  nssTokenSearchType searchType,
695
 
  PRUint32 maximumOpt,
696
 
  PRStatus *statusOpt
697
 
)
698
 
{
699
 
    CK_ATTRIBUTE_PTR attr;
700
 
    CK_ATTRIBUTE email_template[3];
701
 
    CK_ULONG etsize;
702
 
    nssCryptokiObject **objects;
703
 
    NSS_CK_TEMPLATE_START(email_template, attr, etsize);
704
 
    NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_EMAIL, email);
705
 
    /* Set the search to token/session only if provided */
706
 
    if (searchType == nssTokenSearchType_SessionOnly) {
707
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
708
 
    } else if (searchType == nssTokenSearchType_TokenOnly) {
709
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
710
 
    }
711
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
712
 
    NSS_CK_TEMPLATE_FINISH(email_template, attr, etsize);
713
 
    /* now locate the token certs matching this template */
714
 
    objects = find_objects(token, sessionOpt,
715
 
                           email_template, etsize,
716
 
                           maximumOpt, statusOpt);
717
 
    if (!objects) {
718
 
        /* This is to workaround the fact that PKCS#11 doesn't specify
719
 
         * whether the '\0' should be included.  XXX Is that still true?
720
 
         * im - this is not needed by the current softoken.  However, I'm 
721
 
         * leaving it in until I have surveyed more tokens to see if it needed.
722
 
         * well, its needed by the builtin token...
723
 
         */
724
 
        email_template[0].ulValueLen++;
725
 
        objects = find_objects(token, sessionOpt,
726
 
                               email_template, etsize,
727
 
                               maximumOpt, statusOpt);
728
 
    }
729
 
    return objects;
730
 
}
731
 
 
732
 
NSS_IMPLEMENT nssCryptokiObject **
733
 
nssToken_FindCertificatesByID (
734
 
  NSSToken *token,
735
 
  nssSession *sessionOpt,
736
 
  NSSItem *id,
737
 
  nssTokenSearchType searchType,
738
 
  PRUint32 maximumOpt,
739
 
  PRStatus *statusOpt
740
 
)
741
 
{
742
 
    CK_ATTRIBUTE_PTR attr;
743
 
    CK_ATTRIBUTE id_template[3];
744
 
    CK_ULONG idtsize;
745
 
    nssCryptokiObject **objects;
746
 
    NSS_CK_TEMPLATE_START(id_template, attr, idtsize);
747
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
748
 
    /* Set the search to token/session only if provided */
749
 
    if (searchType == nssTokenSearchType_SessionOnly) {
750
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
751
 
    } else if (searchType == nssTokenSearchType_TokenOnly) {
752
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
753
 
    }
754
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
755
 
    NSS_CK_TEMPLATE_FINISH(id_template, attr, idtsize);
756
 
    /* now locate the token certs matching this template */
757
 
    objects = find_objects_by_template(token, sessionOpt,
758
 
                                       id_template, idtsize,
759
 
                                       maximumOpt, statusOpt);
760
 
    return objects;
761
 
}
762
 
 
763
 
/*
764
 
 * decode the serial item and return our result.
765
 
 * NOTE serialDecode's data is really stored in serial. Don't free it.
766
 
 */
767
 
static PRStatus
768
 
nssToken_decodeSerialItem(NSSItem *serial, NSSItem *serialDecode)
769
 
{
770
 
    unsigned char *data = (unsigned char *)serial->data;
771
 
    int data_left, data_len, index;
772
 
 
773
 
    if ((serial->size >= 3) && (data[0] == 0x2)) {
774
 
        /* remove the der encoding of the serial number before generating the
775
 
         * key.. */
776
 
        data_left = serial->size-2;
777
 
        data_len = data[1];
778
 
        index = 2;
779
 
 
780
 
        /* extended length ? (not very likely for a serial number) */
781
 
        if (data_len & 0x80) {
782
 
            int len_count = data_len & 0x7f;
783
 
 
784
 
            data_len = 0;
785
 
            data_left -= len_count;
786
 
            if (data_left > 0) {
787
 
                while (len_count --) {
788
 
                    data_len = (data_len << 8) | data[index++];
789
 
                }
790
 
            } 
791
 
        }
792
 
        /* XXX leaving any leading zeros on the serial number for backwards
793
 
         * compatibility
794
 
         */
795
 
        /* not a valid der, must be just an unlucky serial number value */
796
 
        if (data_len == data_left) {
797
 
            serialDecode->size = data_len;
798
 
            serialDecode->data = &data[index];
799
 
            return PR_SUCCESS;
800
 
        }
801
 
    }
802
 
    return PR_FAILURE;
803
 
}
804
 
 
805
 
NSS_IMPLEMENT nssCryptokiObject *
806
 
nssToken_FindCertificateByIssuerAndSerialNumber (
807
 
  NSSToken *token,
808
 
  nssSession *sessionOpt,
809
 
  NSSDER *issuer,
810
 
  NSSDER *serial,
811
 
  nssTokenSearchType searchType,
812
 
  PRStatus *statusOpt
813
 
)
814
 
{
815
 
    CK_ATTRIBUTE_PTR attr;
816
 
    CK_ATTRIBUTE_PTR serialAttr;
817
 
    CK_ATTRIBUTE cert_template[4];
818
 
    CK_ULONG ctsize;
819
 
    nssCryptokiObject **objects;
820
 
    nssCryptokiObject *rvObject = NULL;
821
 
    NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
822
 
 
823
 
    if (!token) {
824
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
825
 
        if (statusOpt) 
826
 
            *statusOpt = PR_FAILURE;
827
 
        return NULL;
828
 
    }
829
 
    /* Set the search to token/session only if provided */
830
 
    if (searchType == nssTokenSearchType_SessionOnly) {
831
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
832
 
    } else if ((searchType == nssTokenSearchType_TokenOnly) ||
833
 
               (searchType == nssTokenSearchType_TokenForced)) {
834
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
835
 
    }
836
 
    /* Set the unique id */
837
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS,         &g_ck_class_cert);
838
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER,         issuer);
839
 
    serialAttr = attr;
840
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER,  serial);
841
 
    NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
842
 
    /* get the object handle */
843
 
    if (searchType == nssTokenSearchType_TokenForced) {
844
 
        objects = find_objects(token, sessionOpt,
845
 
                               cert_template, ctsize,
846
 
                               1, statusOpt);
847
 
    } else {
848
 
        objects = find_objects_by_template(token, sessionOpt,
849
 
                                       cert_template, ctsize,
850
 
                                       1, statusOpt);
851
 
    }
852
 
    if (objects) {
853
 
        rvObject = objects[0];
854
 
        nss_ZFreeIf(objects);
855
 
    }
856
 
 
857
 
    /*
858
 
     * NSS used to incorrectly store serial numbers in their decoded form.
859
 
     * because of this old tokens have decoded serial numbers.
860
 
     */
861
 
    if (!objects) {
862
 
        NSSItem serialDecode;
863
 
        PRStatus status;
864
 
 
865
 
        status = nssToken_decodeSerialItem(serial, &serialDecode);
866
 
        if (status != PR_SUCCESS) {
867
 
            return NULL;
868
 
        }
869
 
        NSS_CK_SET_ATTRIBUTE_ITEM(serialAttr,CKA_SERIAL_NUMBER,&serialDecode);
870
 
        if (searchType == nssTokenSearchType_TokenForced) {
871
 
            objects = find_objects(token, sessionOpt,
872
 
                               cert_template, ctsize,
873
 
                               1, statusOpt);
874
 
        } else {
875
 
            objects = find_objects_by_template(token, sessionOpt,
876
 
                                       cert_template, ctsize,
877
 
                                       1, statusOpt);
878
 
        }
879
 
        if (objects) {
880
 
            rvObject = objects[0];
881
 
            nss_ZFreeIf(objects);
882
 
        }
883
 
    }
884
 
    return rvObject;
885
 
}
886
 
 
887
 
NSS_IMPLEMENT nssCryptokiObject *
888
 
nssToken_FindCertificateByEncodedCertificate (
889
 
  NSSToken *token,
890
 
  nssSession *sessionOpt,
891
 
  NSSBER *encodedCertificate,
892
 
  nssTokenSearchType searchType,
893
 
  PRStatus *statusOpt
894
 
)
895
 
{
896
 
    CK_ATTRIBUTE_PTR attr;
897
 
    CK_ATTRIBUTE cert_template[3];
898
 
    CK_ULONG ctsize;
899
 
    nssCryptokiObject **objects;
900
 
    nssCryptokiObject *rvObject = NULL;
901
 
    NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
902
 
    /* Set the search to token/session only if provided */
903
 
    if (searchType == nssTokenSearchType_SessionOnly) {
904
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
905
 
    } else if (searchType == nssTokenSearchType_TokenOnly) {
906
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
907
 
    }
908
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
909
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE, encodedCertificate);
910
 
    NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
911
 
    /* get the object handle */
912
 
    objects = find_objects_by_template(token, sessionOpt,
913
 
                                       cert_template, ctsize,
914
 
                                       1, statusOpt);
915
 
    if (objects) {
916
 
        rvObject = objects[0];
917
 
        nss_ZFreeIf(objects);
918
 
    }
919
 
    return rvObject;
920
 
}
921
 
 
922
 
NSS_IMPLEMENT nssCryptokiObject **
923
 
nssToken_FindPrivateKeys (
924
 
  NSSToken *token,
925
 
  nssSession *sessionOpt,
926
 
  nssTokenSearchType searchType,
927
 
  PRUint32 maximumOpt,
928
 
  PRStatus *statusOpt
929
 
)
930
 
{
931
 
    CK_ATTRIBUTE_PTR attr;
932
 
    CK_ATTRIBUTE key_template[2];
933
 
    CK_ULONG ktsize;
934
 
    nssCryptokiObject **objects;
935
 
 
936
 
    NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
937
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey);
938
 
    if (searchType == nssTokenSearchType_SessionOnly) {
939
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
940
 
    } else if (searchType == nssTokenSearchType_TokenOnly) {
941
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
942
 
    }
943
 
    NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
944
 
 
945
 
    objects = find_objects_by_template(token, sessionOpt,
946
 
                                       key_template, ktsize, 
947
 
                                       maximumOpt, statusOpt);
948
 
    return objects;
949
 
}
950
 
 
951
 
/* XXX ?there are no session cert objects, so only search token objects */
952
 
NSS_IMPLEMENT nssCryptokiObject *
953
 
nssToken_FindPrivateKeyByID (
954
 
  NSSToken *token,
955
 
  nssSession *sessionOpt,
956
 
  NSSItem *keyID
957
 
)
958
 
{
959
 
    CK_ATTRIBUTE_PTR attr;
960
 
    CK_ATTRIBUTE key_template[3];
961
 
    CK_ULONG ktsize;
962
 
    nssCryptokiObject **objects;
963
 
    nssCryptokiObject *rvKey = NULL;
964
 
 
965
 
    NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
966
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_privkey);
967
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
968
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID);
969
 
    NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
970
 
 
971
 
    objects = find_objects_by_template(token, sessionOpt,
972
 
                                       key_template, ktsize, 
973
 
                                       1, NULL);
974
 
    if (objects) {
975
 
        rvKey = objects[0];
976
 
        nss_ZFreeIf(objects);
977
 
    }
978
 
    return rvKey;
979
 
}
980
 
 
981
 
/* XXX ?there are no session cert objects, so only search token objects */
982
 
NSS_IMPLEMENT nssCryptokiObject *
983
 
nssToken_FindPublicKeyByID (
984
 
  NSSToken *token,
985
 
  nssSession *sessionOpt,
986
 
  NSSItem *keyID
987
 
)
988
 
{
989
 
    CK_ATTRIBUTE_PTR attr;
990
 
    CK_ATTRIBUTE key_template[3];
991
 
    CK_ULONG ktsize;
992
 
    nssCryptokiObject **objects;
993
 
    nssCryptokiObject *rvKey = NULL;
994
 
 
995
 
    NSS_CK_TEMPLATE_START(key_template, attr, ktsize);
996
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_pubkey);
997
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
998
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, keyID);
999
 
    NSS_CK_TEMPLATE_FINISH(key_template, attr, ktsize);
1000
 
 
1001
 
    objects = find_objects_by_template(token, sessionOpt,
1002
 
                                       key_template, ktsize, 
1003
 
                                       1, NULL);
1004
 
    if (objects) {
1005
 
        rvKey = objects[0];
1006
 
        nss_ZFreeIf(objects);
1007
 
    }
1008
 
    return rvKey;
1009
 
}
1010
 
 
1011
 
static void
1012
 
sha1_hash(NSSItem *input, NSSItem *output)
1013
 
{
1014
 
    NSSAlgorithmAndParameters *ap;
1015
 
    PK11SlotInfo *internal = PK11_GetInternalSlot();
1016
 
    NSSToken *token = PK11Slot_GetNSSToken(internal);
1017
 
    ap = NSSAlgorithmAndParameters_CreateSHA1Digest(NULL);
1018
 
    (void)nssToken_Digest(token, NULL, ap, input, output, NULL);
1019
 
    PK11_FreeSlot(token->pk11slot);
1020
 
    nss_ZFreeIf(ap);
1021
 
}
1022
 
 
1023
 
static void
1024
 
md5_hash(NSSItem *input, NSSItem *output)
1025
 
{
1026
 
    NSSAlgorithmAndParameters *ap;
1027
 
    PK11SlotInfo *internal = PK11_GetInternalSlot();
1028
 
    NSSToken *token = PK11Slot_GetNSSToken(internal);
1029
 
    ap = NSSAlgorithmAndParameters_CreateMD5Digest(NULL);
1030
 
    (void)nssToken_Digest(token, NULL, ap, input, output, NULL);
1031
 
    PK11_FreeSlot(token->pk11slot);
1032
 
    nss_ZFreeIf(ap);
1033
 
}
1034
 
 
1035
 
static CK_TRUST
1036
 
get_ck_trust (
1037
 
  nssTrustLevel nssTrust
1038
 
)
1039
 
{
1040
 
    CK_TRUST t;
1041
 
    switch (nssTrust) {
1042
 
    case nssTrustLevel_NotTrusted: t = CKT_NSS_NOT_TRUSTED; break;
1043
 
    case nssTrustLevel_TrustedDelegator: t = CKT_NSS_TRUSTED_DELEGATOR; 
1044
 
        break;
1045
 
    case nssTrustLevel_ValidDelegator: t = CKT_NSS_VALID_DELEGATOR; break;
1046
 
    case nssTrustLevel_Trusted: t = CKT_NSS_TRUSTED; break;
1047
 
    case nssTrustLevel_MustVerify: t = CKT_NSS_MUST_VERIFY_TRUST; break;
1048
 
    case nssTrustLevel_Unknown:
1049
 
    default: t = CKT_NSS_TRUST_UNKNOWN; break;
1050
 
    }
1051
 
    return t;
1052
 
}
1053
 
 
1054
 
NSS_IMPLEMENT nssCryptokiObject *
1055
 
nssToken_ImportTrust (
1056
 
  NSSToken *tok,
1057
 
  nssSession *sessionOpt,
1058
 
  NSSDER *certEncoding,
1059
 
  NSSDER *certIssuer,
1060
 
  NSSDER *certSerial,
1061
 
  nssTrustLevel serverAuth,
1062
 
  nssTrustLevel clientAuth,
1063
 
  nssTrustLevel codeSigning,
1064
 
  nssTrustLevel emailProtection,
1065
 
  PRBool stepUpApproved,
1066
 
  PRBool asTokenObject
1067
 
)
1068
 
{
1069
 
    nssCryptokiObject *object;
1070
 
    CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST;
1071
 
    CK_TRUST ckSA, ckCA, ckCS, ckEP;
1072
 
    CK_ATTRIBUTE_PTR attr;
1073
 
    CK_ATTRIBUTE trust_tmpl[11];
1074
 
    CK_ULONG tsize;
1075
 
    PRUint8 sha1[20]; /* this is cheating... */
1076
 
    PRUint8 md5[16];
1077
 
    NSSItem sha1_result, md5_result;
1078
 
    sha1_result.data = sha1; sha1_result.size = sizeof sha1;
1079
 
    md5_result.data = md5; md5_result.size = sizeof md5;
1080
 
    sha1_hash(certEncoding, &sha1_result);
1081
 
    md5_hash(certEncoding, &md5_result);
1082
 
    ckSA = get_ck_trust(serverAuth);
1083
 
    ckCA = get_ck_trust(clientAuth);
1084
 
    ckCS = get_ck_trust(codeSigning);
1085
 
    ckEP = get_ck_trust(emailProtection);
1086
 
    NSS_CK_TEMPLATE_START(trust_tmpl, attr, tsize);
1087
 
    if (asTokenObject) {
1088
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1089
 
    } else {
1090
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1091
 
    }
1092
 
    NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS,           tobjc);
1093
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER,          certIssuer);
1094
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER,   certSerial);
1095
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, &sha1_result);
1096
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_MD5_HASH,  &md5_result);
1097
 
    /* now set the trust values */
1098
 
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH,      ckSA);
1099
 
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH,      ckCA);
1100
 
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING,     ckCS);
1101
 
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, ckEP);
1102
 
    if (stepUpApproved) {
1103
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED, 
1104
 
                                  &g_ck_true);
1105
 
    } else {
1106
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TRUST_STEP_UP_APPROVED, 
1107
 
                                  &g_ck_false);
1108
 
    }
1109
 
    NSS_CK_TEMPLATE_FINISH(trust_tmpl, attr, tsize);
1110
 
    /* import the trust object onto the token */
1111
 
    object = import_object(tok, sessionOpt, trust_tmpl, tsize);
1112
 
    if (object && tok->cache) {
1113
 
        nssTokenObjectCache_ImportObject(tok->cache, object, tobjc,
1114
 
                                         trust_tmpl, tsize);
1115
 
    }
1116
 
    return object;
1117
 
}
1118
 
 
1119
 
NSS_IMPLEMENT nssCryptokiObject *
1120
 
nssToken_FindTrustForCertificate (
1121
 
  NSSToken *token,
1122
 
  nssSession *sessionOpt,
1123
 
  NSSDER *certEncoding,
1124
 
  NSSDER *certIssuer,
1125
 
  NSSDER *certSerial,
1126
 
  nssTokenSearchType searchType
1127
 
)
1128
 
{
1129
 
    CK_OBJECT_CLASS tobjc = CKO_NSS_TRUST;
1130
 
    CK_ATTRIBUTE_PTR attr;
1131
 
    CK_ATTRIBUTE tobj_template[5];
1132
 
    CK_ULONG tobj_size;
1133
 
    nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1134
 
    nssCryptokiObject *object = NULL, **objects;
1135
 
 
1136
 
    /* Don't ask the module to use an invalid session handle. */
1137
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1138
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1139
 
        return object;
1140
 
    }
1141
 
 
1142
 
    NSS_CK_TEMPLATE_START(tobj_template, attr, tobj_size);
1143
 
    if (searchType == nssTokenSearchType_TokenOnly) {
1144
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1145
 
    }
1146
 
    NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS,          tobjc);
1147
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ISSUER,         certIssuer);
1148
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SERIAL_NUMBER , certSerial);
1149
 
    NSS_CK_TEMPLATE_FINISH(tobj_template, attr, tobj_size);
1150
 
    objects = find_objects_by_template(token, session,
1151
 
                                       tobj_template, tobj_size,
1152
 
                                       1, NULL);
1153
 
    if (objects) {
1154
 
        object = objects[0];
1155
 
        nss_ZFreeIf(objects);
1156
 
    }
1157
 
    return object;
1158
 
}
1159
 
 
1160
 
NSS_IMPLEMENT nssCryptokiObject *
1161
 
nssToken_ImportCRL (
1162
 
  NSSToken *token,
1163
 
  nssSession *sessionOpt,
1164
 
  NSSDER *subject,
1165
 
  NSSDER *encoding,
1166
 
  PRBool isKRL,
1167
 
  NSSUTF8 *url,
1168
 
  PRBool asTokenObject
1169
 
)
1170
 
{
1171
 
    nssCryptokiObject *object;
1172
 
    CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL;
1173
 
    CK_ATTRIBUTE_PTR attr;
1174
 
    CK_ATTRIBUTE crl_tmpl[6];
1175
 
    CK_ULONG crlsize;
1176
 
 
1177
 
    NSS_CK_TEMPLATE_START(crl_tmpl, attr, crlsize);
1178
 
    if (asTokenObject) {
1179
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1180
 
    } else {
1181
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1182
 
    }
1183
 
    NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS,        crlobjc);
1184
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT,      subject);
1185
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_VALUE,        encoding);
1186
 
    NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_NSS_URL, url);
1187
 
    if (isKRL) {
1188
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_true);
1189
 
    } else {
1190
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_KRL, &g_ck_false);
1191
 
    }
1192
 
    NSS_CK_TEMPLATE_FINISH(crl_tmpl, attr, crlsize);
1193
 
 
1194
 
    /* import the crl object onto the token */
1195
 
    object = import_object(token, sessionOpt, crl_tmpl, crlsize);
1196
 
    if (object && token->cache) {
1197
 
        nssTokenObjectCache_ImportObject(token->cache, object, crlobjc,
1198
 
                                         crl_tmpl, crlsize);
1199
 
    }
1200
 
    return object;
1201
 
}
1202
 
 
1203
 
NSS_IMPLEMENT nssCryptokiObject **
1204
 
nssToken_FindCRLsBySubject (
1205
 
  NSSToken *token,
1206
 
  nssSession *sessionOpt,
1207
 
  NSSDER *subject,
1208
 
  nssTokenSearchType searchType,
1209
 
  PRUint32 maximumOpt,
1210
 
  PRStatus *statusOpt
1211
 
)
1212
 
{
1213
 
    CK_OBJECT_CLASS crlobjc = CKO_NSS_CRL;
1214
 
    CK_ATTRIBUTE_PTR attr;
1215
 
    CK_ATTRIBUTE crlobj_template[3];
1216
 
    CK_ULONG crlobj_size;
1217
 
    nssCryptokiObject **objects = NULL;
1218
 
    nssSession *session = sessionOpt ? sessionOpt : token->defaultSession;
1219
 
 
1220
 
    /* Don't ask the module to use an invalid session handle. */
1221
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1222
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1223
 
        return objects;
1224
 
    }
1225
 
 
1226
 
    NSS_CK_TEMPLATE_START(crlobj_template, attr, crlobj_size);
1227
 
    if (searchType == nssTokenSearchType_SessionOnly) {
1228
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1229
 
    } else if (searchType == nssTokenSearchType_TokenOnly ||
1230
 
               searchType == nssTokenSearchType_TokenForced) {
1231
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1232
 
    }
1233
 
    NSS_CK_SET_ATTRIBUTE_VAR( attr, CKA_CLASS, crlobjc);
1234
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
1235
 
    NSS_CK_TEMPLATE_FINISH(crlobj_template, attr, crlobj_size);
1236
 
 
1237
 
    objects = find_objects_by_template(token, session,
1238
 
                                       crlobj_template, crlobj_size,
1239
 
                                       maximumOpt, statusOpt);
1240
 
    return objects;
1241
 
}
1242
 
 
1243
 
NSS_IMPLEMENT PRStatus
1244
 
nssToken_GetCachedObjectAttributes (
1245
 
  NSSToken *token,
1246
 
  NSSArena *arenaOpt,
1247
 
  nssCryptokiObject *object,
1248
 
  CK_OBJECT_CLASS objclass,
1249
 
  CK_ATTRIBUTE_PTR atemplate,
1250
 
  CK_ULONG atlen
1251
 
)
1252
 
{
1253
 
    if (!token->cache) {
1254
 
        return PR_FAILURE;
1255
 
    }
1256
 
    return nssTokenObjectCache_GetObjectAttributes(token->cache, arenaOpt,
1257
 
                                                   object, objclass,
1258
 
                                                   atemplate, atlen);
1259
 
}
1260
 
 
1261
 
NSS_IMPLEMENT NSSItem *
1262
 
nssToken_Digest (
1263
 
  NSSToken *tok,
1264
 
  nssSession *sessionOpt,
1265
 
  NSSAlgorithmAndParameters *ap,
1266
 
  NSSItem *data,
1267
 
  NSSItem *rvOpt,
1268
 
  NSSArena *arenaOpt
1269
 
)
1270
 
{
1271
 
    CK_RV ckrv;
1272
 
    CK_ULONG digestLen;
1273
 
    CK_BYTE_PTR digest;
1274
 
    NSSItem *rvItem = NULL;
1275
 
    void *epv = nssToken_GetCryptokiEPV(tok);
1276
 
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1277
 
 
1278
 
    /* Don't ask the module to use an invalid session handle. */
1279
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1280
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1281
 
        return rvItem;
1282
 
    }
1283
 
 
1284
 
    nssSession_EnterMonitor(session);
1285
 
    ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
1286
 
    if (ckrv != CKR_OK) {
1287
 
        nssSession_ExitMonitor(session);
1288
 
        return NULL;
1289
 
    }
1290
 
#if 0
1291
 
    /* XXX the standard says this should work, but it doesn't */
1292
 
    ckrv = CKAPI(epv)->C_Digest(session->handle, NULL, 0, NULL, &digestLen);
1293
 
    if (ckrv != CKR_OK) {
1294
 
        nssSession_ExitMonitor(session);
1295
 
        return NULL;
1296
 
    }
1297
 
#endif
1298
 
    digestLen = 0; /* XXX for now */
1299
 
    digest = NULL;
1300
 
    if (rvOpt) {
1301
 
        if (rvOpt->size > 0 && rvOpt->size < digestLen) {
1302
 
            nssSession_ExitMonitor(session);
1303
 
            /* the error should be bad args */
1304
 
            return NULL;
1305
 
        }
1306
 
        if (rvOpt->data) {
1307
 
            digest = rvOpt->data;
1308
 
        }
1309
 
        digestLen = rvOpt->size;
1310
 
    }
1311
 
    if (!digest) {
1312
 
        digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
1313
 
        if (!digest) {
1314
 
            nssSession_ExitMonitor(session);
1315
 
            return NULL;
1316
 
        }
1317
 
    }
1318
 
    ckrv = CKAPI(epv)->C_Digest(session->handle, 
1319
 
                                (CK_BYTE_PTR)data->data, 
1320
 
                                (CK_ULONG)data->size,
1321
 
                                (CK_BYTE_PTR)digest,
1322
 
                                &digestLen);
1323
 
    nssSession_ExitMonitor(session);
1324
 
    if (ckrv != CKR_OK) {
1325
 
        nss_ZFreeIf(digest);
1326
 
        return NULL;
1327
 
    }
1328
 
    if (!rvOpt) {
1329
 
        rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
1330
 
    }
1331
 
    return rvItem;
1332
 
}
1333
 
 
1334
 
NSS_IMPLEMENT PRStatus
1335
 
nssToken_BeginDigest (
1336
 
  NSSToken *tok,
1337
 
  nssSession *sessionOpt,
1338
 
  NSSAlgorithmAndParameters *ap
1339
 
)
1340
 
{
1341
 
    CK_RV ckrv;
1342
 
    void *epv = nssToken_GetCryptokiEPV(tok);
1343
 
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1344
 
 
1345
 
    /* Don't ask the module to use an invalid session handle. */
1346
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1347
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1348
 
        return PR_FAILURE;
1349
 
    }
1350
 
 
1351
 
    nssSession_EnterMonitor(session);
1352
 
    ckrv = CKAPI(epv)->C_DigestInit(session->handle, &ap->mechanism);
1353
 
    nssSession_ExitMonitor(session);
1354
 
    return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
1355
 
}
1356
 
 
1357
 
NSS_IMPLEMENT PRStatus
1358
 
nssToken_ContinueDigest (
1359
 
  NSSToken *tok,
1360
 
  nssSession *sessionOpt,
1361
 
  NSSItem *item
1362
 
)
1363
 
{
1364
 
    CK_RV ckrv;
1365
 
    void *epv = nssToken_GetCryptokiEPV(tok);
1366
 
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1367
 
 
1368
 
    /* Don't ask the module to use an invalid session handle. */
1369
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1370
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1371
 
        return PR_FAILURE;
1372
 
    }
1373
 
 
1374
 
    nssSession_EnterMonitor(session);
1375
 
    ckrv = CKAPI(epv)->C_DigestUpdate(session->handle, 
1376
 
                                      (CK_BYTE_PTR)item->data, 
1377
 
                                      (CK_ULONG)item->size);
1378
 
    nssSession_ExitMonitor(session);
1379
 
    return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
1380
 
}
1381
 
 
1382
 
NSS_IMPLEMENT NSSItem *
1383
 
nssToken_FinishDigest (
1384
 
  NSSToken *tok,
1385
 
  nssSession *sessionOpt,
1386
 
  NSSItem *rvOpt,
1387
 
  NSSArena *arenaOpt
1388
 
)
1389
 
{
1390
 
    CK_RV ckrv;
1391
 
    CK_ULONG digestLen;
1392
 
    CK_BYTE_PTR digest;
1393
 
    NSSItem *rvItem = NULL;
1394
 
    void *epv = nssToken_GetCryptokiEPV(tok);
1395
 
    nssSession *session = (sessionOpt) ? sessionOpt : tok->defaultSession;
1396
 
 
1397
 
    /* Don't ask the module to use an invalid session handle. */
1398
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1399
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1400
 
        return NULL;
1401
 
    }
1402
 
 
1403
 
    nssSession_EnterMonitor(session);
1404
 
    ckrv = CKAPI(epv)->C_DigestFinal(session->handle, NULL, &digestLen);
1405
 
    if (ckrv != CKR_OK || digestLen == 0) {
1406
 
        nssSession_ExitMonitor(session);
1407
 
        return NULL;
1408
 
    }
1409
 
    digest = NULL;
1410
 
    if (rvOpt) {
1411
 
        if (rvOpt->size > 0 && rvOpt->size < digestLen) {
1412
 
            nssSession_ExitMonitor(session);
1413
 
            /* the error should be bad args */
1414
 
            return NULL;
1415
 
        }
1416
 
        if (rvOpt->data) {
1417
 
            digest = rvOpt->data;
1418
 
        }
1419
 
        digestLen = rvOpt->size;
1420
 
    }
1421
 
    if (!digest) {
1422
 
        digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
1423
 
        if (!digest) {
1424
 
            nssSession_ExitMonitor(session);
1425
 
            return NULL;
1426
 
        }
1427
 
    }
1428
 
    ckrv = CKAPI(epv)->C_DigestFinal(session->handle, digest, &digestLen);
1429
 
    nssSession_ExitMonitor(session);
1430
 
    if (ckrv != CKR_OK) {
1431
 
        nss_ZFreeIf(digest);
1432
 
        return NULL;
1433
 
    }
1434
 
    if (!rvOpt) {
1435
 
        rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
1436
 
    }
1437
 
    return rvItem;
1438
 
}
1439
 
 
1440
 
NSS_IMPLEMENT PRBool
1441
 
nssToken_IsPresent (
1442
 
  NSSToken *token
1443
 
)
1444
 
{
1445
 
    return nssSlot_IsTokenPresent(token->slot);
1446
 
}
1447
 
 
1448
 
/* Sigh.  The methods to find objects declared above cause problems with
1449
 
 * the low-level object cache in the softoken -- the objects are found in 
1450
 
 * toto, then one wave of GetAttributes is done, then another.  Having a 
1451
 
 * large number of objects causes the cache to be thrashed, as the objects 
1452
 
 * are gone before there's any chance to ask for their attributes.
1453
 
 * So, for now, bringing back traversal methods for certs.  This way all of 
1454
 
 * the cert's attributes can be grabbed immediately after finding it,
1455
 
 * increasing the likelihood that the cache takes care of it.
1456
 
 */
1457
 
NSS_IMPLEMENT PRStatus
1458
 
nssToken_TraverseCertificates (
1459
 
  NSSToken *token,
1460
 
  nssSession *sessionOpt,
1461
 
  nssTokenSearchType searchType,
1462
 
  PRStatus (* callback)(nssCryptokiObject *instance, void *arg),
1463
 
  void *arg
1464
 
)
1465
 
{
1466
 
    CK_RV ckrv;
1467
 
    CK_ULONG count;
1468
 
    CK_OBJECT_HANDLE *objectHandles;
1469
 
    CK_ATTRIBUTE_PTR attr;
1470
 
    CK_ATTRIBUTE cert_template[2];
1471
 
    CK_ULONG ctsize;
1472
 
    NSSArena *arena;
1473
 
    PRStatus status;
1474
 
    PRUint32 arraySize, numHandles;
1475
 
    nssCryptokiObject **objects;
1476
 
    void *epv = nssToken_GetCryptokiEPV(token);
1477
 
    nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession;
1478
 
 
1479
 
    /* Don't ask the module to use an invalid session handle. */
1480
 
    if (!session || session->handle == CK_INVALID_SESSION) {
1481
 
        PORT_SetError(SEC_ERROR_NO_TOKEN);
1482
 
        return PR_FAILURE;
1483
 
    }
1484
 
 
1485
 
    /* template for all certs */
1486
 
    NSS_CK_TEMPLATE_START(cert_template, attr, ctsize);
1487
 
    if (searchType == nssTokenSearchType_SessionOnly) {
1488
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false);
1489
 
    } else if (searchType == nssTokenSearchType_TokenOnly ||
1490
 
               searchType == nssTokenSearchType_TokenForced) {
1491
 
        NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true);
1492
 
    }
1493
 
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert);
1494
 
    NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize);
1495
 
 
1496
 
    /* the arena is only for the array of object handles */
1497
 
    arena = nssArena_Create();
1498
 
    if (!arena) {
1499
 
        return PR_FAILURE;
1500
 
    }
1501
 
    arraySize = OBJECT_STACK_SIZE;
1502
 
    numHandles = 0;
1503
 
    objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize);
1504
 
    if (!objectHandles) {
1505
 
        goto loser;
1506
 
    }
1507
 
    nssSession_EnterMonitor(session); /* ==== session lock === */
1508
 
    /* Initialize the find with the template */
1509
 
    ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, 
1510
 
                                         cert_template, ctsize);
1511
 
    if (ckrv != CKR_OK) {
1512
 
        nssSession_ExitMonitor(session);
1513
 
        goto loser;
1514
 
    }
1515
 
    while (PR_TRUE) {
1516
 
        /* Issue the find for up to arraySize - numHandles objects */
1517
 
        ckrv = CKAPI(epv)->C_FindObjects(session->handle, 
1518
 
                                         objectHandles + numHandles, 
1519
 
                                         arraySize - numHandles, 
1520
 
                                         &count);
1521
 
        if (ckrv != CKR_OK) {
1522
 
            nssSession_ExitMonitor(session);
1523
 
            goto loser;
1524
 
        }
1525
 
        /* bump the number of found objects */
1526
 
        numHandles += count;
1527
 
        if (numHandles < arraySize) {
1528
 
            break;
1529
 
        }
1530
 
        /* the array is filled, double it and continue */
1531
 
        arraySize *= 2;
1532
 
        objectHandles = nss_ZREALLOCARRAY(objectHandles, 
1533
 
                                          CK_OBJECT_HANDLE, 
1534
 
                                          arraySize);
1535
 
        if (!objectHandles) {
1536
 
            nssSession_ExitMonitor(session);
1537
 
            goto loser;
1538
 
        }
1539
 
    }
1540
 
    ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle);
1541
 
    nssSession_ExitMonitor(session); /* ==== end session lock === */
1542
 
    if (ckrv != CKR_OK) {
1543
 
        goto loser;
1544
 
    }
1545
 
    if (numHandles > 0) {
1546
 
        objects = create_objects_from_handles(token, session,
1547
 
                                              objectHandles, numHandles);
1548
 
        if (objects) {
1549
 
            nssCryptokiObject **op;
1550
 
            for (op = objects; *op; op++) {
1551
 
                status = (*callback)(*op, arg);
1552
 
            }
1553
 
            nss_ZFreeIf(objects);
1554
 
        }
1555
 
    }
1556
 
    nssArena_Destroy(arena);
1557
 
    return PR_SUCCESS;
1558
 
loser:
1559
 
    nssArena_Destroy(arena);
1560
 
    return PR_FAILURE;
1561
 
}
1562
 
 
1563
 
NSS_IMPLEMENT PRBool
1564
 
nssToken_IsPrivateKeyAvailable (
1565
 
  NSSToken *token,
1566
 
  NSSCertificate *c,
1567
 
  nssCryptokiObject *instance
1568
 
)
1569
 
{
1570
 
    CK_OBJECT_CLASS theClass;
1571
 
 
1572
 
    if (token == NULL) return PR_FALSE;
1573
 
    if (c == NULL) return PR_FALSE;
1574
 
 
1575
 
    theClass = CKO_PRIVATE_KEY;
1576
 
    if (!nssSlot_IsLoggedIn(token->slot)) {
1577
 
        theClass = CKO_PUBLIC_KEY;
1578
 
    }
1579
 
    if (PK11_MatchItem(token->pk11slot, instance->handle, theClass) 
1580
 
                                                != CK_INVALID_HANDLE) {
1581
 
        return PR_TRUE;
1582
 
    }
1583
 
    return PR_FALSE;
1584
 
}