Coverage Report

Created: 2024-05-20 06:23

/src/nss/lib/pk11wrap/pk11obj.c
Line
Count
Source (jump to first uncovered line)
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
 * This file manages object type indepentent functions.
6
 */
7
#include <limits.h>
8
#include <stddef.h>
9
10
#include "seccomon.h"
11
#include "secmod.h"
12
#include "secmodi.h"
13
#include "secmodti.h"
14
#include "pkcs11.h"
15
#include "pkcs11t.h"
16
#include "pk11func.h"
17
#include "keyhi.h"
18
#include "secitem.h"
19
#include "secerr.h"
20
#include "sslerr.h"
21
22
57.1k
#define PK11_SEARCH_CHUNKSIZE 10
23
24
/*
25
 * Build a block big enough to hold the data
26
 */
27
SECItem *
28
PK11_BlockData(SECItem *data, unsigned long size)
29
0
{
30
0
    SECItem *newData;
31
32
0
    if (size == 0u)
33
0
        return NULL;
34
35
0
    newData = (SECItem *)PORT_Alloc(sizeof(SECItem));
36
0
    if (newData == NULL)
37
0
        return NULL;
38
39
0
    newData->len = (data->len + (size - 1)) / size;
40
0
    newData->len *= size;
41
42
0
    newData->data = (unsigned char *)PORT_ZAlloc(newData->len);
43
0
    if (newData->data == NULL) {
44
0
        PORT_Free(newData);
45
0
        return NULL;
46
0
    }
47
0
    PORT_Memset(newData->data, newData->len - data->len, newData->len);
48
0
    PORT_Memcpy(newData->data, data->data, data->len);
49
0
    return newData;
50
0
}
51
52
SECStatus
53
PK11_DestroyObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE object)
54
29.6k
{
55
29.6k
    CK_RV crv;
56
57
29.6k
    PK11_EnterSlotMonitor(slot);
58
29.6k
    crv = PK11_GETTAB(slot)->C_DestroyObject(slot->session, object);
59
29.6k
    PK11_ExitSlotMonitor(slot);
60
29.6k
    if (crv != CKR_OK) {
61
0
        return SECFailure;
62
0
    }
63
29.6k
    return SECSuccess;
64
29.6k
}
65
66
SECStatus
67
PK11_DestroyTokenObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE object)
68
0
{
69
0
    CK_RV crv;
70
0
    SECStatus rv = SECSuccess;
71
0
    CK_SESSION_HANDLE rwsession;
72
73
0
    rwsession = PK11_GetRWSession(slot);
74
0
    if (rwsession == CK_INVALID_HANDLE) {
75
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
76
0
        return SECFailure;
77
0
    }
78
79
0
    crv = PK11_GETTAB(slot)->C_DestroyObject(rwsession, object);
80
0
    if (crv != CKR_OK) {
81
0
        rv = SECFailure;
82
0
        PORT_SetError(PK11_MapError(crv));
83
0
    }
84
0
    PK11_RestoreROSession(slot, rwsession);
85
0
    return rv;
86
0
}
87
88
/*
89
 * Read in a single attribute into a SECItem. Allocate space for it with
90
 * PORT_Alloc unless an arena is supplied. In the latter case use the arena
91
 * to allocate the space.
92
 *
93
 * PK11_ReadAttribute sets the 'data' and 'len' fields of the SECItem but
94
 * does not modify its 'type' field.
95
 */
96
SECStatus
97
PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
98
                   CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result)
99
0
{
100
0
    CK_ATTRIBUTE attr = { 0, NULL, 0 };
101
0
    CK_RV crv;
102
103
0
    attr.type = type;
104
105
0
    PK11_EnterSlotMonitor(slot);
106
0
    crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, id, &attr, 1);
107
0
    if (crv != CKR_OK) {
108
0
        PK11_ExitSlotMonitor(slot);
109
0
        PORT_SetError(PK11_MapError(crv));
110
0
        return SECFailure;
111
0
    }
112
0
    if (arena) {
113
0
        attr.pValue = PORT_ArenaAlloc(arena, attr.ulValueLen);
114
0
    } else {
115
0
        attr.pValue = PORT_Alloc(attr.ulValueLen);
116
0
    }
117
0
    if (attr.pValue == NULL) {
118
0
        PK11_ExitSlotMonitor(slot);
119
0
        return SECFailure;
120
0
    }
121
0
    crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, id, &attr, 1);
122
0
    PK11_ExitSlotMonitor(slot);
123
0
    if (crv != CKR_OK) {
124
0
        PORT_SetError(PK11_MapError(crv));
125
0
        if (!arena)
126
0
            PORT_Free(attr.pValue);
127
0
        return SECFailure;
128
0
    }
129
130
0
    result->data = (unsigned char *)attr.pValue;
131
0
    result->len = attr.ulValueLen;
132
133
0
    return SECSuccess;
134
0
}
135
136
/*
137
 * Read in a single attribute into a Ulong.
138
 */
139
CK_ULONG
140
PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
141
                        CK_ATTRIBUTE_TYPE type)
142
13.2k
{
143
13.2k
    CK_ATTRIBUTE attr;
144
13.2k
    CK_ULONG value = CK_UNAVAILABLE_INFORMATION;
145
13.2k
    CK_RV crv;
146
147
13.2k
    PK11_SETATTRS(&attr, type, &value, sizeof(value));
148
149
13.2k
    PK11_EnterSlotMonitor(slot);
150
13.2k
    crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, id, &attr, 1);
151
13.2k
    PK11_ExitSlotMonitor(slot);
152
13.2k
    if (crv != CKR_OK) {
153
0
        PORT_SetError(PK11_MapError(crv));
154
0
    }
155
13.2k
    return value;
156
13.2k
}
157
158
/*
159
 * check to see if a bool has been set.
160
 */
161
CK_BBOOL
162
pk11_HasAttributeSet_Lock(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
163
                          CK_ATTRIBUTE_TYPE type, PRBool haslock)
164
42.8k
{
165
42.8k
    CK_BBOOL ckvalue = CK_FALSE;
166
42.8k
    CK_ATTRIBUTE theTemplate;
167
42.8k
    CK_RV crv;
168
169
    /* Prepare to retrieve the attribute. */
170
42.8k
    PK11_SETATTRS(&theTemplate, type, &ckvalue, sizeof(CK_BBOOL));
171
172
    /* Retrieve attribute value. */
173
42.8k
    if (!haslock)
174
42.8k
        PK11_EnterSlotMonitor(slot);
175
42.8k
    crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, id,
176
42.8k
                                                 &theTemplate, 1);
177
42.8k
    if (!haslock)
178
42.8k
        PK11_ExitSlotMonitor(slot);
179
42.8k
    if (crv != CKR_OK) {
180
0
        PORT_SetError(PK11_MapError(crv));
181
0
        return CK_FALSE;
182
0
    }
183
184
42.8k
    return ckvalue;
185
42.8k
}
186
187
CK_BBOOL
188
PK11_HasAttributeSet(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
189
                     CK_ATTRIBUTE_TYPE type, PRBool haslock)
190
42.8k
{
191
42.8k
    PR_ASSERT(haslock == PR_FALSE);
192
42.8k
    return pk11_HasAttributeSet_Lock(slot, id, type, PR_FALSE);
193
42.8k
}
194
195
/*
196
 * returns a full list of attributes. Allocate space for them. If an arena is
197
 * provided, allocate space out of the arena.
198
 */
199
CK_RV
200
PK11_GetAttributes(PLArenaPool *arena, PK11SlotInfo *slot,
201
                   CK_OBJECT_HANDLE obj, CK_ATTRIBUTE *attr, int count)
202
13.2k
{
203
13.2k
    int i;
204
    /* make pedantic happy... note that it's only used arena != NULL */
205
13.2k
    void *mark = NULL;
206
13.2k
    CK_RV crv;
207
13.2k
    if (slot->session == CK_INVALID_HANDLE)
208
0
        return CKR_SESSION_HANDLE_INVALID;
209
210
    /*
211
     * first get all the lengths of the parameters.
212
     */
213
13.2k
    PK11_EnterSlotMonitor(slot);
214
13.2k
    crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, obj, attr, count);
215
13.2k
    if (crv != CKR_OK) {
216
0
        PK11_ExitSlotMonitor(slot);
217
0
        return crv;
218
0
    }
219
220
13.2k
    if (arena) {
221
13.2k
        mark = PORT_ArenaMark(arena);
222
13.2k
        if (mark == NULL)
223
0
            return CKR_HOST_MEMORY;
224
13.2k
    }
225
226
    /*
227
     * now allocate space to store the results.
228
     */
229
66.2k
    for (i = 0; i < count; i++) {
230
52.9k
        if (attr[i].ulValueLen == 0)
231
0
            continue;
232
52.9k
        if (arena) {
233
52.9k
            attr[i].pValue = PORT_ArenaAlloc(arena, attr[i].ulValueLen);
234
52.9k
            if (attr[i].pValue == NULL) {
235
                /* arena failures, just release the mark */
236
0
                PORT_ArenaRelease(arena, mark);
237
0
                PK11_ExitSlotMonitor(slot);
238
0
                return CKR_HOST_MEMORY;
239
0
            }
240
52.9k
        } else {
241
0
            attr[i].pValue = PORT_Alloc(attr[i].ulValueLen);
242
0
            if (attr[i].pValue == NULL) {
243
                /* Separate malloc failures, loop to release what we have
244
                 * so far */
245
0
                int j;
246
0
                for (j = 0; j < i; j++) {
247
0
                    PORT_Free(attr[j].pValue);
248
                    /* don't give the caller pointers to freed memory */
249
0
                    attr[j].pValue = NULL;
250
0
                }
251
0
                PK11_ExitSlotMonitor(slot);
252
0
                return CKR_HOST_MEMORY;
253
0
            }
254
0
        }
255
52.9k
    }
256
257
    /*
258
     * finally get the results.
259
     */
260
13.2k
    crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session, obj, attr, count);
261
13.2k
    PK11_ExitSlotMonitor(slot);
262
13.2k
    if (crv != CKR_OK) {
263
0
        if (arena) {
264
0
            PORT_ArenaRelease(arena, mark);
265
0
        } else {
266
0
            for (i = 0; i < count; i++) {
267
0
                PORT_Free(attr[i].pValue);
268
                /* don't give the caller pointers to freed memory */
269
0
                attr[i].pValue = NULL;
270
0
            }
271
0
        }
272
13.2k
    } else if (arena && mark) {
273
13.2k
        PORT_ArenaUnmark(arena, mark);
274
13.2k
    }
275
13.2k
    return crv;
276
13.2k
}
277
278
PRBool
279
PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
280
16.3k
{
281
16.3k
    return (PRBool)PK11_HasAttributeSet(slot, handle, CKA_TOKEN, PR_FALSE);
282
16.3k
}
283
284
char *
285
PK11_GetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id)
286
0
{
287
0
    char *nickname = NULL;
288
0
    SECItem result;
289
0
    SECStatus rv;
290
291
0
    rv = PK11_ReadAttribute(slot, id, CKA_LABEL, NULL, &result);
292
0
    if (rv != SECSuccess) {
293
0
        return NULL;
294
0
    }
295
296
0
    nickname = PORT_ZAlloc(result.len + 1);
297
0
    if (nickname == NULL) {
298
0
        PORT_Free(result.data);
299
0
        return NULL;
300
0
    }
301
0
    PORT_Memcpy(nickname, result.data, result.len);
302
0
    PORT_Free(result.data);
303
0
    return nickname;
304
0
}
305
306
SECStatus
307
PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
308
                       const char *nickname)
309
0
{
310
0
    int len = PORT_Strlen(nickname);
311
0
    CK_ATTRIBUTE setTemplate;
312
0
    CK_RV crv;
313
0
    CK_SESSION_HANDLE rwsession;
314
315
0
    if (len < 0) {
316
0
        return SECFailure;
317
0
    }
318
319
0
    PK11_SETATTRS(&setTemplate, CKA_LABEL, (CK_CHAR *)nickname, len);
320
0
    rwsession = PK11_GetRWSession(slot);
321
0
    if (rwsession == CK_INVALID_HANDLE) {
322
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
323
0
        return SECFailure;
324
0
    }
325
0
    crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, id,
326
0
                                                 &setTemplate, 1);
327
0
    PK11_RestoreROSession(slot, rwsession);
328
0
    if (crv != CKR_OK) {
329
0
        PORT_SetError(PK11_MapError(crv));
330
0
        return SECFailure;
331
0
    }
332
0
    return SECSuccess;
333
0
}
334
335
/*
336
 * strip leading zero's from key material
337
 */
338
void
339
pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib)
340
5.36k
{
341
5.36k
    char *ptr = (char *)attrib->pValue;
342
5.36k
    unsigned long len = attrib->ulValueLen;
343
344
5.36k
    while ((len > 1) && (*ptr == 0)) {
345
0
        len--;
346
0
        ptr++;
347
0
    }
348
5.36k
    attrib->pValue = ptr;
349
5.36k
    attrib->ulValueLen = len;
350
5.36k
}
351
352
/*
353
 * get a new session on a slot. If we run out of session, use the slot's
354
 * 'exclusive' session. In this case owner becomes false.
355
 */
356
CK_SESSION_HANDLE
357
pk11_GetNewSession(PK11SlotInfo *slot, PRBool *owner)
358
100k
{
359
100k
    CK_SESSION_HANDLE session;
360
100k
    *owner = PR_TRUE;
361
100k
    if (!slot->isThreadSafe)
362
0
        PK11_EnterSlotMonitor(slot);
363
100k
    if (PK11_GETTAB(slot)->C_OpenSession(slot->slotID, CKF_SERIAL_SESSION,
364
100k
                                         slot, pk11_notify, &session) != CKR_OK) {
365
0
        *owner = PR_FALSE;
366
0
        session = slot->session;
367
0
    }
368
100k
    if (!slot->isThreadSafe)
369
0
        PK11_ExitSlotMonitor(slot);
370
371
100k
    return session;
372
100k
}
373
374
void
375
pk11_CloseSession(PK11SlotInfo *slot, CK_SESSION_HANDLE session, PRBool owner)
376
104k
{
377
104k
    if (!owner)
378
4.04k
        return;
379
100k
    if (!slot->isThreadSafe)
380
0
        PK11_EnterSlotMonitor(slot);
381
100k
    (void)PK11_GETTAB(slot)->C_CloseSession(session);
382
100k
    if (!slot->isThreadSafe)
383
0
        PK11_ExitSlotMonitor(slot);
384
100k
}
385
386
SECStatus
387
PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
388
                     const CK_ATTRIBUTE *theTemplate, int count,
389
                     PRBool token, CK_OBJECT_HANDLE *objectID)
390
3.85k
{
391
3.85k
    CK_SESSION_HANDLE rwsession;
392
3.85k
    CK_RV crv;
393
3.85k
    SECStatus rv = SECSuccess;
394
395
3.85k
    rwsession = session;
396
3.85k
    if (token) {
397
0
        rwsession = PK11_GetRWSession(slot);
398
3.85k
    } else if (rwsession == CK_INVALID_HANDLE) {
399
3.85k
        rwsession = slot->session;
400
3.85k
        if (rwsession != CK_INVALID_HANDLE)
401
3.85k
            PK11_EnterSlotMonitor(slot);
402
3.85k
    }
403
3.85k
    if (rwsession == CK_INVALID_HANDLE) {
404
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
405
0
        return SECFailure;
406
0
    }
407
3.85k
    crv = PK11_GETTAB(slot)->C_CreateObject(rwsession,
408
3.85k
                                            /* cast away const :-( */ (CK_ATTRIBUTE_PTR)theTemplate,
409
3.85k
                                            count, objectID);
410
3.85k
    if (crv != CKR_OK) {
411
707
        PORT_SetError(PK11_MapError(crv));
412
707
        rv = SECFailure;
413
707
    }
414
3.85k
    if (token) {
415
0
        PK11_RestoreROSession(slot, rwsession);
416
3.85k
    } else if (session == CK_INVALID_HANDLE) {
417
3.85k
        PK11_ExitSlotMonitor(slot);
418
3.85k
    }
419
420
3.85k
    return rv;
421
3.85k
}
422
423
/* This function may add a maximum of 9 attributes. */
424
unsigned int
425
pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
426
6.51k
{
427
428
6.51k
    const static CK_ATTRIBUTE_TYPE attrTypes[12] = {
429
6.51k
        CKA_ENCRYPT, CKA_DECRYPT, 0 /* DIGEST */, CKA_SIGN,
430
6.51k
        CKA_SIGN_RECOVER, CKA_VERIFY, CKA_VERIFY_RECOVER, 0 /* GEN */,
431
6.51k
        0 /* GEN PAIR */, CKA_WRAP, CKA_UNWRAP, CKA_DERIVE
432
6.51k
    };
433
434
6.51k
    const CK_ATTRIBUTE_TYPE *pType = attrTypes;
435
6.51k
    CK_ATTRIBUTE *attr = attrs;
436
6.51k
    CK_FLAGS test = CKF_ENCRYPT;
437
438
6.51k
    PR_ASSERT(!(flags & ~CKF_KEY_OPERATION_FLAGS));
439
6.51k
    flags &= CKF_KEY_OPERATION_FLAGS;
440
441
41.8k
    for (; flags && test <= CKF_DERIVE; test <<= 1, ++pType) {
442
35.3k
        if (test & flags) {
443
13.0k
            flags ^= test;
444
13.0k
            PR_ASSERT(*pType);
445
13.0k
            PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue);
446
13.0k
            ++attr;
447
13.0k
        }
448
35.3k
    }
449
6.51k
    return (attr - attrs);
450
6.51k
}
451
452
/*
453
 * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE
454
 * and PK11_ATTR_PUBLIC are set.
455
 */
456
PRBool
457
pk11_BadAttrFlags(PK11AttrFlags attrFlags)
458
43.7k
{
459
43.7k
    PK11AttrFlags trueFlags = attrFlags & 0x55555555;
460
43.7k
    PK11AttrFlags falseFlags = (attrFlags >> 1) & 0x55555555;
461
43.7k
    return ((trueFlags & falseFlags) != 0);
462
43.7k
}
463
464
/*
465
 * This function may add a maximum of 5 attributes.
466
 * The caller must make sure the attribute flags don't have conflicts.
467
 */
468
unsigned int
469
pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs,
470
                           CK_BBOOL *ckTrue, CK_BBOOL *ckFalse)
471
28.5k
{
472
28.5k
    const static CK_ATTRIBUTE_TYPE attrTypes[5] = {
473
28.5k
        CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_SENSITIVE,
474
28.5k
        CKA_EXTRACTABLE
475
28.5k
    };
476
477
28.5k
    const CK_ATTRIBUTE_TYPE *pType = attrTypes;
478
28.5k
    CK_ATTRIBUTE *attr = attrs;
479
28.5k
    PK11AttrFlags test = PK11_ATTR_TOKEN;
480
481
28.5k
    PR_ASSERT(!pk11_BadAttrFlags(attrFlags));
482
483
    /* we test two related bitflags in each iteration */
484
95.2k
    for (; attrFlags && test <= PK11_ATTR_EXTRACTABLE; test <<= 2, ++pType) {
485
66.7k
        if (test & attrFlags) {
486
100
            attrFlags ^= test;
487
100
            PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue);
488
100
            ++attr;
489
66.6k
        } else if ((test << 1) & attrFlags) {
490
53.2k
            attrFlags ^= (test << 1);
491
53.2k
            PK11_SETATTRS(attr, *pType, ckFalse, sizeof *ckFalse);
492
53.2k
            ++attr;
493
53.2k
        }
494
66.7k
    }
495
28.5k
    return (attr - attrs);
496
28.5k
}
497
498
/*
499
 * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually
500
 * set up a signature to get the signaure length.
501
 */
502
static int
503
pk11_backupGetSignLength(SECKEYPrivateKey *key)
504
0
{
505
0
    PK11SlotInfo *slot = key->pkcs11Slot;
506
0
    CK_MECHANISM mech = { 0, NULL, 0 };
507
0
    PRBool owner = PR_TRUE;
508
0
    CK_SESSION_HANDLE session;
509
0
    CK_ULONG len;
510
0
    CK_RV crv;
511
0
    unsigned char h_data[20] = { 0 };
512
0
    unsigned char buf[20]; /* obviously to small */
513
0
    CK_ULONG smallLen = sizeof(buf);
514
515
0
    mech.mechanism = PK11_MapSignKeyType(key->keyType);
516
517
0
    session = pk11_GetNewSession(slot, &owner);
518
0
    if (!owner || !(slot->isThreadSafe))
519
0
        PK11_EnterSlotMonitor(slot);
520
0
    crv = PK11_GETTAB(slot)->C_SignInit(session, &mech, key->pkcs11ID);
521
0
    if (crv != CKR_OK) {
522
0
        if (!owner || !(slot->isThreadSafe))
523
0
            PK11_ExitSlotMonitor(slot);
524
0
        pk11_CloseSession(slot, session, owner);
525
0
        PORT_SetError(PK11_MapError(crv));
526
0
        return -1;
527
0
    }
528
0
    len = 0;
529
0
    crv = PK11_GETTAB(slot)->C_Sign(session, h_data, sizeof(h_data),
530
0
                                    NULL, &len);
531
    /* now call C_Sign with too small a buffer to clear the session state */
532
0
    (void)PK11_GETTAB(slot)->C_Sign(session, h_data, sizeof(h_data), buf, &smallLen);
533
534
0
    if (!owner || !(slot->isThreadSafe))
535
0
        PK11_ExitSlotMonitor(slot);
536
0
    pk11_CloseSession(slot, session, owner);
537
0
    if (crv != CKR_OK) {
538
0
        PORT_SetError(PK11_MapError(crv));
539
0
        return -1;
540
0
    }
541
0
    return len;
542
0
}
543
544
/*
545
 * get the length of a signature object based on the key
546
 */
547
int
548
PK11_SignatureLen(SECKEYPrivateKey *key)
549
0
{
550
0
    int val;
551
0
    SECItem attributeItem = { siBuffer, NULL, 0 };
552
0
    SECStatus rv;
553
0
    int length;
554
555
0
    switch (key->keyType) {
556
0
        case rsaKey:
557
0
            val = PK11_GetPrivateModulusLen(key);
558
0
            if (val == -1) {
559
0
                return pk11_backupGetSignLength(key);
560
0
            }
561
0
            return (unsigned long)val;
562
563
0
        case fortezzaKey:
564
0
            return 40;
565
566
0
        case dsaKey:
567
0
            rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_SUBPRIME,
568
0
                                    NULL, &attributeItem);
569
0
            if (rv == SECSuccess) {
570
0
                length = attributeItem.len;
571
0
                if ((length > 0) && attributeItem.data[0] == 0) {
572
0
                    length--;
573
0
                }
574
0
                PORT_Free(attributeItem.data);
575
0
                return length * 2;
576
0
            }
577
0
            return pk11_backupGetSignLength(key);
578
0
        case edKey:
579
0
        case ecKey:
580
0
            rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_EC_PARAMS,
581
0
                                    NULL, &attributeItem);
582
0
            if (rv == SECSuccess) {
583
0
                length = SECKEY_ECParamsToBasePointOrderLen(&attributeItem);
584
0
                PORT_Free(attributeItem.data);
585
0
                if (length != 0) {
586
0
                    length = ((length + 7) / 8) * 2;
587
0
                    return length;
588
0
                }
589
0
            }
590
0
            return pk11_backupGetSignLength(key);
591
0
        default:
592
0
            break;
593
0
    }
594
0
    PORT_SetError(SEC_ERROR_INVALID_KEY);
595
0
    return 0;
596
0
}
597
598
/*
599
 * copy a key (or any other object) on a token
600
 */
601
CK_OBJECT_HANDLE
602
PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject)
603
0
{
604
0
    CK_OBJECT_HANDLE destObject;
605
0
    CK_RV crv;
606
607
0
    PK11_EnterSlotMonitor(slot);
608
0
    crv = PK11_GETTAB(slot)->C_CopyObject(slot->session, srcObject, NULL, 0,
609
0
                                          &destObject);
610
0
    PK11_ExitSlotMonitor(slot);
611
0
    if (crv == CKR_OK)
612
0
        return destObject;
613
0
    PORT_SetError(PK11_MapError(crv));
614
0
    return CK_INVALID_HANDLE;
615
0
}
616
617
PRBool
618
pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs,
619
                        CK_ATTRIBUTE_TYPE target)
620
32.1k
{
621
60.1k
    for (; numAttrs > 0; ++attr, --numAttrs) {
622
27.9k
        if (attr->type == target)
623
0
            return PR_TRUE;
624
27.9k
    }
625
32.1k
    return PR_FALSE;
626
32.1k
}
627
628
/*
629
 * Recover the Signed data. We need this because our old verify can't
630
 * figure out which hash algorithm to use until we decryptted this.
631
 */
632
SECStatus
633
PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig,
634
                   SECItem *dsig, void *wincx)
635
323
{
636
323
    PK11SlotInfo *slot = key->pkcs11Slot;
637
323
    CK_OBJECT_HANDLE id = key->pkcs11ID;
638
323
    CK_MECHANISM mech = { 0, NULL, 0 };
639
323
    PRBool owner = PR_TRUE;
640
323
    CK_SESSION_HANDLE session;
641
323
    CK_ULONG len;
642
323
    CK_RV crv;
643
644
323
    mech.mechanism = PK11_MapSignKeyType(key->keyType);
645
646
323
    if (slot == NULL) {
647
0
        slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
648
0
                                              CKF_VERIFY_RECOVER, 0, wincx);
649
0
        if (slot == NULL) {
650
0
            PORT_SetError(SEC_ERROR_NO_MODULE);
651
0
            return SECFailure;
652
0
        }
653
0
        id = PK11_ImportPublicKey(slot, key, PR_FALSE);
654
323
    } else {
655
323
        PK11_ReferenceSlot(slot);
656
323
    }
657
658
323
    if (id == CK_INVALID_HANDLE) {
659
0
        PK11_FreeSlot(slot);
660
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
661
0
        return SECFailure;
662
0
    }
663
664
323
    session = pk11_GetNewSession(slot, &owner);
665
323
    if (!owner || !(slot->isThreadSafe))
666
0
        PK11_EnterSlotMonitor(slot);
667
323
    crv = PK11_GETTAB(slot)->C_VerifyRecoverInit(session, &mech, id);
668
323
    if (crv != CKR_OK) {
669
0
        if (!owner || !(slot->isThreadSafe))
670
0
            PK11_ExitSlotMonitor(slot);
671
0
        pk11_CloseSession(slot, session, owner);
672
0
        PORT_SetError(PK11_MapError(crv));
673
0
        PK11_FreeSlot(slot);
674
0
        return SECFailure;
675
0
    }
676
323
    len = dsig->len;
677
323
    crv = PK11_GETTAB(slot)->C_VerifyRecover(session, sig->data,
678
323
                                             sig->len, dsig->data, &len);
679
323
    if (!owner || !(slot->isThreadSafe))
680
0
        PK11_ExitSlotMonitor(slot);
681
323
    pk11_CloseSession(slot, session, owner);
682
323
    dsig->len = len;
683
323
    if (crv != CKR_OK) {
684
318
        PORT_SetError(PK11_MapError(crv));
685
318
        PK11_FreeSlot(slot);
686
318
        return SECFailure;
687
318
    }
688
5
    PK11_FreeSlot(slot);
689
5
    return SECSuccess;
690
323
}
691
692
/*
693
 * verify a signature from its hash.
694
 */
695
SECStatus
696
PK11_Verify(SECKEYPublicKey *key, const SECItem *sig, const SECItem *hash,
697
            void *wincx)
698
548
{
699
548
    CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
700
548
    return PK11_VerifyWithMechanism(key, mech, NULL, sig, hash, wincx);
701
548
}
702
703
/*
704
 * Verify a signature from its hash using the given algorithm.
705
 */
706
SECStatus
707
PK11_VerifyWithMechanism(SECKEYPublicKey *key, CK_MECHANISM_TYPE mechanism,
708
                         const SECItem *param, const SECItem *sig,
709
                         const SECItem *hash, void *wincx)
710
1.70k
{
711
1.70k
    PK11SlotInfo *slot = key->pkcs11Slot;
712
1.70k
    CK_OBJECT_HANDLE id = key->pkcs11ID;
713
1.70k
    CK_MECHANISM mech = { 0, NULL, 0 };
714
1.70k
    PRBool owner = PR_TRUE;
715
1.70k
    CK_SESSION_HANDLE session;
716
1.70k
    CK_RV crv;
717
718
1.70k
    mech.mechanism = mechanism;
719
1.70k
    if (param) {
720
525
        mech.pParameter = param->data;
721
525
        mech.ulParameterLen = param->len;
722
525
    }
723
724
1.70k
    if (slot == NULL) {
725
1.25k
        unsigned int length = 0;
726
1.25k
        if ((mech.mechanism == CKM_DSA) &&
727
            /* 129 is 1024 bits translated to bytes and
728
             * padded with an optional '0' to maintain a
729
             * positive sign */
730
1.25k
            (key->u.dsa.params.prime.len > 129)) {
731
            /* we need to get a slot that not only can do DSA, but can do DSA2
732
             * key lengths */
733
2
            length = key->u.dsa.params.prime.len;
734
2
            if (key->u.dsa.params.prime.data[0] == 0) {
735
0
                length--;
736
0
            }
737
            /* convert keysize to bits for slot lookup */
738
2
            length *= 8;
739
2
        }
740
1.25k
        slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
741
1.25k
                                              CKF_VERIFY, length, wincx);
742
1.25k
        if (slot == NULL) {
743
0
            PORT_SetError(SEC_ERROR_NO_MODULE);
744
0
            return SECFailure;
745
0
        }
746
1.25k
        id = PK11_ImportPublicKey(slot, key, PR_FALSE);
747
748
1.25k
    } else {
749
453
        PK11_ReferenceSlot(slot);
750
453
    }
751
752
1.70k
    if (id == CK_INVALID_HANDLE) {
753
95
        PK11_FreeSlot(slot);
754
95
        PORT_SetError(SEC_ERROR_BAD_KEY);
755
95
        return SECFailure;
756
95
    }
757
758
1.61k
    session = pk11_GetNewSession(slot, &owner);
759
1.61k
    if (!owner || !(slot->isThreadSafe))
760
0
        PK11_EnterSlotMonitor(slot);
761
1.61k
    crv = PK11_GETTAB(slot)->C_VerifyInit(session, &mech, id);
762
1.61k
    if (crv != CKR_OK) {
763
0
        if (!owner || !(slot->isThreadSafe))
764
0
            PK11_ExitSlotMonitor(slot);
765
0
        pk11_CloseSession(slot, session, owner);
766
0
        PK11_FreeSlot(slot);
767
0
        PORT_SetError(PK11_MapError(crv));
768
0
        return SECFailure;
769
0
    }
770
1.61k
    crv = PK11_GETTAB(slot)->C_Verify(session, hash->data,
771
1.61k
                                      hash->len, sig->data, sig->len);
772
1.61k
    if (!owner || !(slot->isThreadSafe))
773
0
        PK11_ExitSlotMonitor(slot);
774
1.61k
    pk11_CloseSession(slot, session, owner);
775
1.61k
    PK11_FreeSlot(slot);
776
1.61k
    if (crv != CKR_OK) {
777
1.61k
        PORT_SetError(PK11_MapError(crv));
778
1.61k
        return SECFailure;
779
1.61k
    }
780
0
    return SECSuccess;
781
1.61k
}
782
783
/*
784
 * sign a hash. The algorithm is determined by the key.
785
 */
786
SECStatus
787
PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash)
788
0
{
789
0
    CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
790
0
    return PK11_SignWithMechanism(key, mech, NULL, sig, hash);
791
0
}
792
793
/*
794
 * Sign a hash using the given algorithm.
795
 */
796
SECStatus
797
PK11_SignWithMechanism(SECKEYPrivateKey *key, CK_MECHANISM_TYPE mechanism,
798
                       const SECItem *param, SECItem *sig, const SECItem *hash)
799
0
{
800
0
    PK11SlotInfo *slot = key->pkcs11Slot;
801
0
    CK_MECHANISM mech = { 0, NULL, 0 };
802
0
    PRBool owner = PR_TRUE;
803
0
    CK_SESSION_HANDLE session;
804
0
    PRBool haslock = PR_FALSE;
805
0
    CK_ULONG len;
806
0
    CK_RV crv;
807
808
0
    mech.mechanism = mechanism;
809
0
    if (param) {
810
0
        mech.pParameter = param->data;
811
0
        mech.ulParameterLen = param->len;
812
0
    }
813
814
0
    if (SECKEY_HAS_ATTRIBUTE_SET(key, CKA_PRIVATE)) {
815
0
        PK11_HandlePasswordCheck(slot, key->wincx);
816
0
    }
817
818
0
    session = pk11_GetNewSession(slot, &owner);
819
0
    haslock = (!owner || !(slot->isThreadSafe));
820
0
    if (haslock)
821
0
        PK11_EnterSlotMonitor(slot);
822
0
    crv = PK11_GETTAB(slot)->C_SignInit(session, &mech, key->pkcs11ID);
823
0
    if (crv != CKR_OK) {
824
0
        if (haslock)
825
0
            PK11_ExitSlotMonitor(slot);
826
0
        pk11_CloseSession(slot, session, owner);
827
0
        PORT_SetError(PK11_MapError(crv));
828
0
        return SECFailure;
829
0
    }
830
831
    /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
832
     * do C_Login with CKU_CONTEXT_SPECIFIC
833
     * between C_SignInit and C_Sign */
834
0
    if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
835
0
        PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
836
0
    }
837
838
0
    len = sig->len;
839
0
    crv = PK11_GETTAB(slot)->C_Sign(session, hash->data,
840
0
                                    hash->len, sig->data, &len);
841
0
    if (haslock)
842
0
        PK11_ExitSlotMonitor(slot);
843
0
    pk11_CloseSession(slot, session, owner);
844
0
    sig->len = len;
845
0
    if (crv != CKR_OK) {
846
0
        PORT_SetError(PK11_MapError(crv));
847
0
        return SECFailure;
848
0
    }
849
0
    return SECSuccess;
850
0
}
851
852
/*
853
 * sign data with a MAC key.
854
 */
855
SECStatus
856
PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism,
857
                    SECItem *param, SECItem *sig, const SECItem *data)
858
0
{
859
0
    PK11SlotInfo *slot = symKey->slot;
860
0
    CK_MECHANISM mech = { 0, NULL, 0 };
861
0
    PRBool owner = PR_TRUE;
862
0
    CK_SESSION_HANDLE session;
863
0
    PRBool haslock = PR_FALSE;
864
0
    CK_ULONG len;
865
0
    CK_RV crv;
866
867
0
    mech.mechanism = mechanism;
868
0
    if (param) {
869
0
        mech.pParameter = param->data;
870
0
        mech.ulParameterLen = param->len;
871
0
    }
872
873
0
    session = pk11_GetNewSession(slot, &owner);
874
0
    haslock = (!owner || !(slot->isThreadSafe));
875
0
    if (haslock)
876
0
        PK11_EnterSlotMonitor(slot);
877
0
    crv = PK11_GETTAB(slot)->C_SignInit(session, &mech, symKey->objectID);
878
0
    if (crv != CKR_OK) {
879
0
        if (haslock)
880
0
            PK11_ExitSlotMonitor(slot);
881
0
        pk11_CloseSession(slot, session, owner);
882
0
        PORT_SetError(PK11_MapError(crv));
883
0
        return SECFailure;
884
0
    }
885
886
0
    len = sig->len;
887
0
    crv = PK11_GETTAB(slot)->C_Sign(session, data->data,
888
0
                                    data->len, sig->data, &len);
889
0
    if (haslock)
890
0
        PK11_ExitSlotMonitor(slot);
891
0
    pk11_CloseSession(slot, session, owner);
892
0
    sig->len = len;
893
0
    if (crv != CKR_OK) {
894
0
        PORT_SetError(PK11_MapError(crv));
895
0
        return SECFailure;
896
0
    }
897
0
    return SECSuccess;
898
0
}
899
900
SECStatus
901
PK11_Decrypt(PK11SymKey *symKey,
902
             CK_MECHANISM_TYPE mechanism, SECItem *param,
903
             unsigned char *out, unsigned int *outLen,
904
             unsigned int maxLen,
905
             const unsigned char *enc, unsigned encLen)
906
0
{
907
0
    PK11SlotInfo *slot = symKey->slot;
908
0
    CK_MECHANISM mech = { 0, NULL, 0 };
909
0
    CK_ULONG len = maxLen;
910
0
    PRBool owner = PR_TRUE;
911
0
    CK_SESSION_HANDLE session;
912
0
    PRBool haslock = PR_FALSE;
913
0
    CK_RV crv;
914
915
0
    mech.mechanism = mechanism;
916
0
    if (param) {
917
0
        mech.pParameter = param->data;
918
0
        mech.ulParameterLen = param->len;
919
0
    }
920
921
0
    session = pk11_GetNewSession(slot, &owner);
922
0
    haslock = (!owner || !slot->isThreadSafe);
923
0
    if (haslock)
924
0
        PK11_EnterSlotMonitor(slot);
925
0
    crv = PK11_GETTAB(slot)->C_DecryptInit(session, &mech, symKey->objectID);
926
0
    if (crv != CKR_OK) {
927
0
        if (haslock)
928
0
            PK11_ExitSlotMonitor(slot);
929
0
        pk11_CloseSession(slot, session, owner);
930
0
        PORT_SetError(PK11_MapError(crv));
931
0
        return SECFailure;
932
0
    }
933
934
0
    crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen,
935
0
                                       out, &len);
936
0
    if (haslock)
937
0
        PK11_ExitSlotMonitor(slot);
938
0
    pk11_CloseSession(slot, session, owner);
939
0
    if (crv != CKR_OK) {
940
0
        PORT_SetError(PK11_MapError(crv));
941
0
        return SECFailure;
942
0
    }
943
0
    *outLen = len;
944
0
    return SECSuccess;
945
0
}
946
947
SECStatus
948
PK11_Encrypt(PK11SymKey *symKey,
949
             CK_MECHANISM_TYPE mechanism, SECItem *param,
950
             unsigned char *out, unsigned int *outLen,
951
             unsigned int maxLen,
952
             const unsigned char *data, unsigned int dataLen)
953
0
{
954
0
    PK11SlotInfo *slot = symKey->slot;
955
0
    CK_MECHANISM mech = { 0, NULL, 0 };
956
0
    CK_ULONG len = maxLen;
957
0
    PRBool owner = PR_TRUE;
958
0
    CK_SESSION_HANDLE session;
959
0
    PRBool haslock = PR_FALSE;
960
0
    CK_RV crv;
961
962
0
    mech.mechanism = mechanism;
963
0
    if (param) {
964
0
        mech.pParameter = param->data;
965
0
        mech.ulParameterLen = param->len;
966
0
    }
967
968
0
    session = pk11_GetNewSession(slot, &owner);
969
0
    haslock = (!owner || !slot->isThreadSafe);
970
0
    if (haslock)
971
0
        PK11_EnterSlotMonitor(slot);
972
0
    crv = PK11_GETTAB(slot)->C_EncryptInit(session, &mech, symKey->objectID);
973
0
    if (crv != CKR_OK) {
974
0
        if (haslock)
975
0
            PK11_ExitSlotMonitor(slot);
976
0
        pk11_CloseSession(slot, session, owner);
977
0
        PORT_SetError(PK11_MapError(crv));
978
0
        return SECFailure;
979
0
    }
980
0
    crv = PK11_GETTAB(slot)->C_Encrypt(session, (unsigned char *)data,
981
0
                                       dataLen, out, &len);
982
0
    if (haslock)
983
0
        PK11_ExitSlotMonitor(slot);
984
0
    pk11_CloseSession(slot, session, owner);
985
0
    if (crv != CKR_OK) {
986
0
        PORT_SetError(PK11_MapError(crv));
987
0
        return SECFailure;
988
0
    }
989
0
    *outLen = len;
990
0
    return SECSuccess;
991
0
}
992
993
static SECStatus
994
pk11_PrivDecryptRaw(SECKEYPrivateKey *key,
995
                    unsigned char *data, unsigned *outLen, unsigned int maxLen,
996
                    const unsigned char *enc, unsigned encLen,
997
                    CK_MECHANISM_PTR mech)
998
0
{
999
0
    PK11SlotInfo *slot = key->pkcs11Slot;
1000
0
    CK_ULONG out = maxLen;
1001
0
    PRBool owner = PR_TRUE;
1002
0
    CK_SESSION_HANDLE session;
1003
0
    PRBool haslock = PR_FALSE;
1004
0
    CK_RV crv;
1005
1006
0
    if (key->keyType != rsaKey) {
1007
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
1008
0
        return SECFailure;
1009
0
    }
1010
1011
    /* Why do we do a PK11_handle check here? for simple
1012
     * decryption? .. because the user may have asked for 'ask always'
1013
     * and this is a private key operation. In practice, thought, it's mute
1014
     * since only servers wind up using this function */
1015
0
    if (SECKEY_HAS_ATTRIBUTE_SET(key, CKA_PRIVATE)) {
1016
0
        PK11_HandlePasswordCheck(slot, key->wincx);
1017
0
    }
1018
0
    session = pk11_GetNewSession(slot, &owner);
1019
0
    haslock = (!owner || !(slot->isThreadSafe));
1020
0
    if (haslock)
1021
0
        PK11_EnterSlotMonitor(slot);
1022
0
    crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, key->pkcs11ID);
1023
0
    if (crv != CKR_OK) {
1024
0
        if (haslock)
1025
0
            PK11_ExitSlotMonitor(slot);
1026
0
        pk11_CloseSession(slot, session, owner);
1027
0
        PORT_SetError(PK11_MapError(crv));
1028
0
        return SECFailure;
1029
0
    }
1030
1031
    /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then
1032
     * do C_Login with CKU_CONTEXT_SPECIFIC
1033
     * between C_DecryptInit and C_Decrypt
1034
     * ... But see note above about servers */
1035
0
    if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
1036
0
        PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
1037
0
    }
1038
1039
0
    crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen,
1040
0
                                       data, &out);
1041
0
    if (haslock)
1042
0
        PK11_ExitSlotMonitor(slot);
1043
0
    pk11_CloseSession(slot, session, owner);
1044
0
    *outLen = out;
1045
0
    if (crv != CKR_OK) {
1046
0
        PORT_SetError(PK11_MapError(crv));
1047
0
        return SECFailure;
1048
0
    }
1049
0
    return SECSuccess;
1050
0
}
1051
1052
SECStatus
1053
PK11_PubDecryptRaw(SECKEYPrivateKey *key,
1054
                   unsigned char *data, unsigned *outLen, unsigned int maxLen,
1055
                   const unsigned char *enc, unsigned encLen)
1056
0
{
1057
0
    CK_MECHANISM mech = { CKM_RSA_X_509, NULL, 0 };
1058
0
    return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
1059
0
}
1060
1061
SECStatus
1062
PK11_PrivDecryptPKCS1(SECKEYPrivateKey *key,
1063
                      unsigned char *data, unsigned *outLen, unsigned int maxLen,
1064
                      const unsigned char *enc, unsigned encLen)
1065
0
{
1066
0
    CK_MECHANISM mech = { CKM_RSA_PKCS, NULL, 0 };
1067
0
    return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
1068
0
}
1069
1070
static SECStatus
1071
pk11_PubEncryptRaw(SECKEYPublicKey *key,
1072
                   unsigned char *out, unsigned int *outLen,
1073
                   unsigned int maxLen,
1074
                   const unsigned char *data, unsigned dataLen,
1075
                   CK_MECHANISM_PTR mech, void *wincx)
1076
0
{
1077
0
    PK11SlotInfo *slot;
1078
0
    CK_OBJECT_HANDLE id;
1079
0
    CK_ULONG len = maxLen;
1080
0
    PRBool owner = PR_TRUE;
1081
0
    CK_SESSION_HANDLE session;
1082
0
    CK_RV crv;
1083
1084
0
    slot = PK11_GetBestSlotWithAttributes(mech->mechanism, CKF_ENCRYPT, 0, wincx);
1085
0
    if (slot == NULL) {
1086
0
        PORT_SetError(SEC_ERROR_NO_MODULE);
1087
0
        return SECFailure;
1088
0
    }
1089
1090
0
    id = PK11_ImportPublicKey(slot, key, PR_FALSE);
1091
1092
0
    if (id == CK_INVALID_HANDLE) {
1093
0
        PK11_FreeSlot(slot);
1094
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
1095
0
        return SECFailure;
1096
0
    }
1097
1098
0
    session = pk11_GetNewSession(slot, &owner);
1099
0
    if (!owner || !(slot->isThreadSafe))
1100
0
        PK11_EnterSlotMonitor(slot);
1101
0
    crv = PK11_GETTAB(slot)->C_EncryptInit(session, mech, id);
1102
0
    if (crv != CKR_OK) {
1103
0
        if (!owner || !(slot->isThreadSafe))
1104
0
            PK11_ExitSlotMonitor(slot);
1105
0
        pk11_CloseSession(slot, session, owner);
1106
0
        PK11_FreeSlot(slot);
1107
0
        PORT_SetError(PK11_MapError(crv));
1108
0
        return SECFailure;
1109
0
    }
1110
0
    crv = PK11_GETTAB(slot)->C_Encrypt(session, (unsigned char *)data, dataLen,
1111
0
                                       out, &len);
1112
0
    if (!owner || !(slot->isThreadSafe))
1113
0
        PK11_ExitSlotMonitor(slot);
1114
0
    pk11_CloseSession(slot, session, owner);
1115
0
    PK11_FreeSlot(slot);
1116
0
    *outLen = len;
1117
0
    if (crv != CKR_OK) {
1118
0
        PORT_SetError(PK11_MapError(crv));
1119
0
        return SECFailure;
1120
0
    }
1121
0
    return SECSuccess;
1122
0
}
1123
1124
SECStatus
1125
PK11_PubEncryptRaw(SECKEYPublicKey *key,
1126
                   unsigned char *enc,
1127
                   const unsigned char *data, unsigned dataLen,
1128
                   void *wincx)
1129
0
{
1130
0
    CK_MECHANISM mech = { CKM_RSA_X_509, NULL, 0 };
1131
0
    unsigned int outLen;
1132
0
    if (!key || key->keyType != rsaKey) {
1133
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
1134
0
        return SECFailure;
1135
0
    }
1136
0
    outLen = SECKEY_PublicKeyStrength(key);
1137
0
    return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
1138
0
                              wincx);
1139
0
}
1140
1141
SECStatus
1142
PK11_PubEncryptPKCS1(SECKEYPublicKey *key,
1143
                     unsigned char *enc,
1144
                     const unsigned char *data, unsigned dataLen,
1145
                     void *wincx)
1146
0
{
1147
0
    CK_MECHANISM mech = { CKM_RSA_PKCS, NULL, 0 };
1148
0
    unsigned int outLen;
1149
0
    if (!key || key->keyType != rsaKey) {
1150
0
        PORT_SetError(SEC_ERROR_BAD_KEY);
1151
0
        return SECFailure;
1152
0
    }
1153
0
    outLen = SECKEY_PublicKeyStrength(key);
1154
0
    return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
1155
0
                              wincx);
1156
0
}
1157
1158
SECStatus
1159
PK11_PrivDecrypt(SECKEYPrivateKey *key,
1160
                 CK_MECHANISM_TYPE mechanism, SECItem *param,
1161
                 unsigned char *out, unsigned int *outLen,
1162
                 unsigned int maxLen,
1163
                 const unsigned char *enc, unsigned encLen)
1164
0
{
1165
0
    CK_MECHANISM mech = { mechanism, NULL, 0 };
1166
0
    if (param) {
1167
0
        mech.pParameter = param->data;
1168
0
        mech.ulParameterLen = param->len;
1169
0
    }
1170
0
    return pk11_PrivDecryptRaw(key, out, outLen, maxLen, enc, encLen, &mech);
1171
0
}
1172
1173
SECStatus
1174
PK11_PubEncrypt(SECKEYPublicKey *key,
1175
                CK_MECHANISM_TYPE mechanism, SECItem *param,
1176
                unsigned char *out, unsigned int *outLen,
1177
                unsigned int maxLen,
1178
                const unsigned char *data, unsigned dataLen,
1179
                void *wincx)
1180
0
{
1181
0
    CK_MECHANISM mech = { mechanism, NULL, 0 };
1182
0
    if (param) {
1183
0
        mech.pParameter = param->data;
1184
0
        mech.ulParameterLen = param->len;
1185
0
    }
1186
0
    return pk11_PubEncryptRaw(key, out, outLen, maxLen, data, dataLen, &mech,
1187
0
                              wincx);
1188
0
}
1189
1190
SECKEYPrivateKey *
1191
PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1192
                   CK_MECHANISM_TYPE wrapType, SECItem *param,
1193
                   SECItem *wrappedKey, SECItem *label,
1194
                   SECItem *idValue, PRBool perm, PRBool sensitive,
1195
                   CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage,
1196
                   int usageCount, void *wincx)
1197
0
{
1198
0
    CK_BBOOL cktrue = CK_TRUE;
1199
0
    CK_BBOOL ckfalse = CK_FALSE;
1200
0
    CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
1201
0
    CK_ATTRIBUTE keyTemplate[15];
1202
0
    int templateCount = 0;
1203
0
    CK_OBJECT_HANDLE privKeyID;
1204
0
    CK_MECHANISM mechanism;
1205
0
    CK_ATTRIBUTE *attrs = keyTemplate;
1206
0
    SECItem *param_free = NULL, *ck_id = NULL;
1207
0
    CK_RV crv;
1208
0
    CK_SESSION_HANDLE rwsession;
1209
0
    PK11SymKey *newKey = NULL;
1210
0
    int i;
1211
1212
0
    if (!slot || !wrappedKey || !idValue) {
1213
        /* SET AN ERROR!!! */
1214
0
        return NULL;
1215
0
    }
1216
1217
0
    ck_id = PK11_MakeIDFromPubKey(idValue);
1218
0
    if (!ck_id) {
1219
0
        return NULL;
1220
0
    }
1221
1222
0
    PK11_SETATTRS(attrs, CKA_TOKEN, perm ? &cktrue : &ckfalse,
1223
0
                  sizeof(cktrue));
1224
0
    attrs++;
1225
0
    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
1226
0
    attrs++;
1227
0
    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
1228
0
    attrs++;
1229
0
    PK11_SETATTRS(attrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse,
1230
0
                  sizeof(cktrue));
1231
0
    attrs++;
1232
0
    PK11_SETATTRS(attrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse,
1233
0
                  sizeof(cktrue));
1234
0
    attrs++;
1235
0
    if (label && label->data) {
1236
0
        PK11_SETATTRS(attrs, CKA_LABEL, label->data, label->len);
1237
0
        attrs++;
1238
0
    }
1239
0
    PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
1240
0
    attrs++;
1241
0
    for (i = 0; i < usageCount; i++) {
1242
0
        PK11_SETATTRS(attrs, usage[i], &cktrue, sizeof(cktrue));
1243
0
        attrs++;
1244
0
    }
1245
1246
0
    if (PK11_IsInternal(slot)) {
1247
0
        PK11_SETATTRS(attrs, CKA_NSS_DB, idValue->data,
1248
0
                      idValue->len);
1249
0
        attrs++;
1250
0
    }
1251
1252
0
    templateCount = attrs - keyTemplate;
1253
0
    PR_ASSERT(templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)));
1254
1255
0
    mechanism.mechanism = wrapType;
1256
0
    if (!param)
1257
0
        param = param_free = PK11_ParamFromIV(wrapType, NULL);
1258
0
    if (param) {
1259
0
        mechanism.pParameter = param->data;
1260
0
        mechanism.ulParameterLen = param->len;
1261
0
    } else {
1262
0
        mechanism.pParameter = NULL;
1263
0
        mechanism.ulParameterLen = 0;
1264
0
    }
1265
1266
0
    if (wrappingKey->slot != slot) {
1267
0
        newKey = pk11_CopyToSlot(slot, wrapType, CKA_UNWRAP, wrappingKey);
1268
0
    } else {
1269
0
        newKey = PK11_ReferenceSymKey(wrappingKey);
1270
0
    }
1271
1272
0
    if (newKey) {
1273
0
        if (perm) {
1274
            /* Get RW Session will either lock the monitor if necessary,
1275
             *  or return a thread safe session handle, or fail. */
1276
0
            rwsession = PK11_GetRWSession(slot);
1277
0
        } else {
1278
0
            rwsession = slot->session;
1279
0
            if (rwsession != CK_INVALID_HANDLE)
1280
0
                PK11_EnterSlotMonitor(slot);
1281
0
        }
1282
        /* This is a lot a work to deal with fussy PKCS #11 modules
1283
         * that can't bother to return BAD_DATA when presented with an
1284
         * invalid session! */
1285
0
        if (rwsession == CK_INVALID_HANDLE) {
1286
0
            PORT_SetError(SEC_ERROR_BAD_DATA);
1287
0
            goto loser;
1288
0
        }
1289
0
        crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism,
1290
0
                                             newKey->objectID,
1291
0
                                             wrappedKey->data,
1292
0
                                             wrappedKey->len, keyTemplate,
1293
0
                                             templateCount, &privKeyID);
1294
1295
0
        if (perm) {
1296
0
            PK11_RestoreROSession(slot, rwsession);
1297
0
        } else {
1298
0
            PK11_ExitSlotMonitor(slot);
1299
0
        }
1300
0
        PK11_FreeSymKey(newKey);
1301
0
        newKey = NULL;
1302
0
    } else {
1303
0
        crv = CKR_FUNCTION_NOT_SUPPORTED;
1304
0
    }
1305
1306
0
    SECITEM_FreeItem(ck_id, PR_TRUE);
1307
0
    ck_id = NULL;
1308
1309
0
    if (crv != CKR_OK) {
1310
        /* we couldn't unwrap the key, use the internal module to do the
1311
         * unwrap, then load the new key into the token */
1312
0
        PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1313
1314
0
        if (int_slot && (slot != int_slot)) {
1315
0
            SECKEYPrivateKey *privKey = PK11_UnwrapPrivKey(int_slot,
1316
0
                                                           wrappingKey, wrapType, param, wrappedKey, label,
1317
0
                                                           idValue, PR_FALSE, PR_FALSE,
1318
0
                                                           keyType, usage, usageCount, wincx);
1319
0
            if (privKey) {
1320
0
                SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(slot, privKey,
1321
0
                                                                NULL, perm, sensitive);
1322
0
                SECKEY_DestroyPrivateKey(privKey);
1323
0
                PK11_FreeSlot(int_slot);
1324
0
                SECITEM_FreeItem(param_free, PR_TRUE);
1325
0
                return newPrivKey;
1326
0
            }
1327
0
        }
1328
0
        if (int_slot)
1329
0
            PK11_FreeSlot(int_slot);
1330
0
        PORT_SetError(PK11_MapError(crv));
1331
0
        SECITEM_FreeItem(param_free, PR_TRUE);
1332
0
        return NULL;
1333
0
    }
1334
0
    SECITEM_FreeItem(param_free, PR_TRUE);
1335
0
    return PK11_MakePrivKey(slot, nullKey, PR_FALSE, privKeyID, wincx);
1336
1337
0
loser:
1338
0
    PK11_FreeSymKey(newKey);
1339
0
    SECITEM_FreeItem(ck_id, PR_TRUE);
1340
0
    SECITEM_FreeItem(param_free, PR_TRUE);
1341
0
    return NULL;
1342
0
}
1343
1344
/*
1345
 * Now we're going to wrap a SECKEYPrivateKey with a PK11SymKey
1346
 * The strategy is to get both keys to reside in the same slot,
1347
 * one that can perform the desired crypto mechanism and then
1348
 * call C_WrapKey after all the setup has taken place.
1349
 */
1350
SECStatus
1351
PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
1352
                 SECKEYPrivateKey *privKey, CK_MECHANISM_TYPE wrapType,
1353
                 SECItem *param, SECItem *wrappedKey, void *wincx)
1354
0
{
1355
0
    PK11SlotInfo *privSlot = privKey->pkcs11Slot; /* The slot where
1356
                                                   * the private key
1357
                                                   * we are going to
1358
                                                   * wrap lives.
1359
                                                   */
1360
0
    PK11SymKey *newSymKey = NULL;
1361
0
    SECKEYPrivateKey *newPrivKey = NULL;
1362
0
    SECItem *param_free = NULL;
1363
0
    CK_ULONG len = wrappedKey->len;
1364
0
    CK_MECHANISM mech;
1365
0
    CK_RV crv;
1366
1367
0
    if (!privSlot || !PK11_DoesMechanism(privSlot, wrapType)) {
1368
        /* Figure out a slot that does the mechanism and try to import
1369
         * the private key onto that slot.
1370
         */
1371
0
        PK11SlotInfo *int_slot = PK11_GetInternalSlot();
1372
1373
0
        privSlot = int_slot; /* The private key has a new home */
1374
0
        newPrivKey = PK11_LoadPrivKey(privSlot, privKey, NULL, PR_FALSE, PR_FALSE);
1375
        /* newPrivKey has allocated its own reference to the slot, so it's
1376
         * safe until we destroy newPrivkey.
1377
         */
1378
0
        PK11_FreeSlot(int_slot);
1379
0
        if (newPrivKey == NULL) {
1380
0
            return SECFailure;
1381
0
        }
1382
0
        privKey = newPrivKey;
1383
0
    }
1384
1385
0
    if (privSlot != wrappingKey->slot) {
1386
0
        newSymKey = pk11_CopyToSlot(privSlot, wrapType, CKA_WRAP,
1387
0
                                    wrappingKey);
1388
0
        wrappingKey = newSymKey;
1389
0
    }
1390
1391
0
    if (wrappingKey == NULL) {
1392
0
        if (newPrivKey) {
1393
0
            SECKEY_DestroyPrivateKey(newPrivKey);
1394
0
        }
1395
0
        return SECFailure;
1396
0
    }
1397
0
    mech.mechanism = wrapType;
1398
0
    if (!param) {
1399
0
        param = param_free = PK11_ParamFromIV(wrapType, NULL);
1400
0
    }
1401
0
    if (param) {
1402
0
        mech.pParameter = param->data;
1403
0
        mech.ulParameterLen = param->len;
1404
0
    } else {
1405
0
        mech.pParameter = NULL;
1406
0
        mech.ulParameterLen = 0;
1407
0
    }
1408
1409
0
    PK11_EnterSlotMonitor(privSlot);
1410
0
    crv = PK11_GETTAB(privSlot)->C_WrapKey(privSlot->session, &mech,
1411
0
                                           wrappingKey->objectID,
1412
0
                                           privKey->pkcs11ID,
1413
0
                                           wrappedKey->data, &len);
1414
0
    PK11_ExitSlotMonitor(privSlot);
1415
1416
0
    if (newSymKey) {
1417
0
        PK11_FreeSymKey(newSymKey);
1418
0
    }
1419
0
    if (newPrivKey) {
1420
0
        SECKEY_DestroyPrivateKey(newPrivKey);
1421
0
    }
1422
0
    if (param_free) {
1423
0
        SECITEM_FreeItem(param_free, PR_TRUE);
1424
0
    }
1425
1426
0
    if (crv != CKR_OK) {
1427
0
        PORT_SetError(PK11_MapError(crv));
1428
0
        return SECFailure;
1429
0
    }
1430
1431
0
    wrappedKey->len = len;
1432
0
    return SECSuccess;
1433
0
}
1434
1435
#if 0
1436
/*
1437
 * Sample code relating to linked list returned by PK11_FindGenericObjects
1438
 */
1439
1440
/*
1441
 * You can walk the list with the following code:
1442
 */
1443
    firstObj = PK11_FindGenericObjects(slot, objClass);
1444
    for (thisObj=firstObj;
1445
         thisObj;
1446
         thisObj=PK11_GetNextGenericObject(thisObj)) {
1447
        /* operate on thisObj */
1448
    }
1449
/*
1450
 * If you want a particular object from the list...
1451
 */
1452
    firstObj = PK11_FindGenericObjects(slot, objClass);
1453
    for (thisObj=firstObj;
1454
         thisObj;
1455
         thisObj=PK11_GetNextGenericObject(thisObj)) {
1456
      if (isMyObj(thisObj)) {
1457
       if ( thisObj == firstObj) {
1458
                /* NOTE: firstObj could be NULL at this point */
1459
      firstObj = PK11_GetNextGenericObject(thsObj);
1460
       }
1461
       PK11_UnlinkGenericObject(thisObj);
1462
            myObj = thisObj;
1463
            break;
1464
        }
1465
    }
1466
1467
    PK11_DestroyGenericObjects(firstObj);
1468
1469
      /* use myObj */
1470
1471
    PK11_DestroyGenericObject(myObj);
1472
#endif /* sample code */
1473
1474
/*
1475
 * return a linked, non-circular list of generic objects.
1476
 * If you are only interested
1477
 * in one object, just use the first object in the list. To find the
1478
 * rest of the list use PK11_GetNextGenericObject() to return the next object.
1479
 */
1480
PK11GenericObject *
1481
PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass)
1482
0
{
1483
0
    CK_ATTRIBUTE template[1];
1484
0
    CK_ATTRIBUTE *attrs = template;
1485
0
    CK_OBJECT_HANDLE *objectIDs = NULL;
1486
0
    PK11GenericObject *lastObj = NULL, *obj;
1487
0
    PK11GenericObject *firstObj = NULL;
1488
0
    int i, count = 0;
1489
1490
0
    PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass));
1491
0
    attrs++;
1492
1493
0
    objectIDs = pk11_FindObjectsByTemplate(slot, template, 1, &count);
1494
0
    if (objectIDs == NULL) {
1495
0
        return NULL;
1496
0
    }
1497
1498
    /* where we connect our object once we've created it.. */
1499
0
    for (i = 0; i < count; i++) {
1500
0
        obj = PORT_New(PK11GenericObject);
1501
0
        if (!obj) {
1502
0
            if (firstObj) {
1503
0
                PK11_DestroyGenericObjects(firstObj);
1504
0
            }
1505
0
            PORT_Free(objectIDs);
1506
0
            return NULL;
1507
0
        }
1508
        /* initialize it */
1509
0
        obj->slot = PK11_ReferenceSlot(slot);
1510
0
        obj->objectID = objectIDs[i];
1511
0
        obj->owner = PR_FALSE;
1512
0
        obj->next = NULL;
1513
0
        obj->prev = NULL;
1514
1515
        /* link it in */
1516
0
        if (firstObj == NULL) {
1517
0
            firstObj = obj;
1518
0
        } else {
1519
0
            PK11_LinkGenericObject(lastObj, obj);
1520
0
        }
1521
0
        lastObj = obj;
1522
0
    }
1523
0
    PORT_Free(objectIDs);
1524
0
    return firstObj;
1525
0
}
1526
1527
/*
1528
 * get the Next Object in the list.
1529
 */
1530
PK11GenericObject *
1531
PK11_GetNextGenericObject(PK11GenericObject *object)
1532
0
{
1533
0
    return object->next;
1534
0
}
1535
1536
PK11GenericObject *
1537
PK11_GetPrevGenericObject(PK11GenericObject *object)
1538
0
{
1539
0
    return object->prev;
1540
0
}
1541
1542
/*
1543
 * Link a single object into a new list.
1544
 * if the object is already in another list, remove it first.
1545
 */
1546
SECStatus
1547
PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object)
1548
0
{
1549
0
    PK11_UnlinkGenericObject(object);
1550
0
    object->prev = list;
1551
0
    object->next = list->next;
1552
0
    list->next = object;
1553
0
    if (object->next != NULL) {
1554
0
        object->next->prev = object;
1555
0
    }
1556
0
    return SECSuccess;
1557
0
}
1558
1559
/*
1560
 * remove an object from the list. If the object isn't already in
1561
 * a list unlink becomes a noop.
1562
 */
1563
SECStatus
1564
PK11_UnlinkGenericObject(PK11GenericObject *object)
1565
0
{
1566
0
    if (object->prev != NULL) {
1567
0
        object->prev->next = object->next;
1568
0
    }
1569
0
    if (object->next != NULL) {
1570
0
        object->next->prev = object->prev;
1571
0
    }
1572
1573
0
    object->next = NULL;
1574
0
    object->prev = NULL;
1575
0
    return SECSuccess;
1576
0
}
1577
1578
/*
1579
 * This function removes a single object from the list and destroys it.
1580
 * For an already unlinked object there is no difference between
1581
 * PK11_DestroyGenericObject and PK11_DestroyGenericObjects
1582
 */
1583
SECStatus
1584
PK11_DestroyGenericObject(PK11GenericObject *object)
1585
0
{
1586
0
    if (object == NULL) {
1587
0
        return SECSuccess;
1588
0
    }
1589
1590
0
    PK11_UnlinkGenericObject(object);
1591
0
    if (object->slot) {
1592
0
        if (object->owner) {
1593
0
            PK11_DestroyObject(object->slot, object->objectID);
1594
0
        }
1595
0
        PK11_FreeSlot(object->slot);
1596
0
    }
1597
0
    PORT_Free(object);
1598
0
    return SECSuccess;
1599
0
}
1600
1601
/*
1602
 * walk down a link list of generic objects destroying them.
1603
 * This will destroy all objects in a list that the object is linked into.
1604
 * (the list is traversed in both directions).
1605
 */
1606
SECStatus
1607
PK11_DestroyGenericObjects(PK11GenericObject *objects)
1608
0
{
1609
0
    PK11GenericObject *nextObject;
1610
0
    PK11GenericObject *prevObject;
1611
1612
0
    if (objects == NULL) {
1613
0
        return SECSuccess;
1614
0
    }
1615
1616
0
    nextObject = objects->next;
1617
0
    prevObject = objects->prev;
1618
1619
    /* delete all the objects after it in the list */
1620
0
    for (; objects; objects = nextObject) {
1621
0
        nextObject = objects->next;
1622
0
        PK11_DestroyGenericObject(objects);
1623
0
    }
1624
    /* delete all the objects before it in the list */
1625
0
    for (objects = prevObject; objects; objects = prevObject) {
1626
0
        prevObject = objects->prev;
1627
0
        PK11_DestroyGenericObject(objects);
1628
0
    }
1629
0
    return SECSuccess;
1630
0
}
1631
1632
/*
1633
 * Hand Create a new object and return the Generic object for our new object.
1634
 */
1635
PK11GenericObject *
1636
pk11_CreateGenericObjectHelper(PK11SlotInfo *slot,
1637
                               const CK_ATTRIBUTE *pTemplate,
1638
                               int count, PRBool token, PRBool owner)
1639
0
{
1640
0
    CK_OBJECT_HANDLE objectID;
1641
0
    PK11GenericObject *obj;
1642
0
    CK_RV crv;
1643
1644
0
    PK11_EnterSlotMonitor(slot);
1645
0
    crv = PK11_CreateNewObject(slot, slot->session, pTemplate, count,
1646
0
                               token, &objectID);
1647
0
    PK11_ExitSlotMonitor(slot);
1648
0
    if (crv != CKR_OK) {
1649
0
        PORT_SetError(PK11_MapError(crv));
1650
0
        return NULL;
1651
0
    }
1652
1653
0
    obj = PORT_New(PK11GenericObject);
1654
0
    if (!obj) {
1655
        /* error set by PORT_New */
1656
0
        return NULL;
1657
0
    }
1658
1659
    /* initialize it */
1660
0
    obj->slot = PK11_ReferenceSlot(slot);
1661
0
    obj->objectID = objectID;
1662
0
    obj->owner = owner;
1663
0
    obj->next = NULL;
1664
0
    obj->prev = NULL;
1665
0
    return obj;
1666
0
}
1667
1668
/* This is the classic interface. Applications would call this function to
1669
 * create new object that would not be destroyed later. This lead to resource
1670
 * leaks (and thus memory leaks in the PKCS #11 module).  To solve this we have
1671
 * a new interface that automatically marks objects created on the fly to be
1672
 * destroyed later.
1673
 * The old interface is preserved because applications like Mozilla purposefully
1674
 * leak the reference to be found later with PK11_FindGenericObjects. New
1675
 * applications should use the new interface PK11_CreateManagedGenericObject */
1676
PK11GenericObject *
1677
PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
1678
                         int count, PRBool token)
1679
0
{
1680
0
    return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
1681
0
                                          PR_FALSE);
1682
0
}
1683
1684
/* Use this interface. It will automatically destroy any temporary objects
1685
 * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still
1686
 * need to be destroyed by hand with PK11_DestroyTokenObject.
1687
 */
1688
PK11GenericObject *
1689
PK11_CreateManagedGenericObject(PK11SlotInfo *slot,
1690
                                const CK_ATTRIBUTE *pTemplate, int count, PRBool token)
1691
0
{
1692
0
    return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
1693
0
                                          !token);
1694
0
}
1695
1696
CK_OBJECT_HANDLE
1697
PK11_GetObjectHandle(PK11ObjectType objType, void *objSpec,
1698
                     PK11SlotInfo **slotp)
1699
0
{
1700
0
    CK_OBJECT_HANDLE handle = CK_INVALID_HANDLE;
1701
0
    PK11SlotInfo *slot = NULL;
1702
1703
0
    switch (objType) {
1704
0
        case PK11_TypeGeneric:
1705
0
            slot = ((PK11GenericObject *)objSpec)->slot;
1706
0
            handle = ((PK11GenericObject *)objSpec)->objectID;
1707
0
            break;
1708
0
        case PK11_TypePrivKey:
1709
0
            slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot;
1710
0
            handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID;
1711
0
            break;
1712
0
        case PK11_TypePubKey:
1713
0
            slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot;
1714
0
            handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID;
1715
0
            break;
1716
0
        case PK11_TypeSymKey:
1717
0
            slot = ((PK11SymKey *)objSpec)->slot;
1718
0
            handle = ((PK11SymKey *)objSpec)->objectID;
1719
0
            break;
1720
0
        case PK11_TypeCert:
1721
0
            handle = PK11_FindObjectForCert((CERTCertificate *)objSpec, NULL,
1722
0
                                            &slot);
1723
0
            break;
1724
0
        default:
1725
0
            PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1726
0
            break;
1727
0
    }
1728
0
    if (slotp) {
1729
0
        *slotp = slot;
1730
0
    }
1731
    /* paranoia. If the object doesn't have a slot, then it's handle isn't
1732
     * valid either */
1733
0
    if (slot == NULL) {
1734
0
        handle = CK_INVALID_HANDLE;
1735
0
    }
1736
0
    return handle;
1737
0
}
1738
1739
/*
1740
 * Change an attribute on a raw object
1741
 */
1742
SECStatus
1743
PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec,
1744
                       CK_ATTRIBUTE_TYPE attrType, SECItem *item)
1745
0
{
1746
0
    PK11SlotInfo *slot = NULL;
1747
0
    CK_OBJECT_HANDLE handle = 0;
1748
0
    CK_ATTRIBUTE setTemplate;
1749
0
    CK_RV crv;
1750
0
    CK_SESSION_HANDLE rwsession;
1751
1752
0
    handle = PK11_GetObjectHandle(objType, objSpec, &slot);
1753
0
    if (handle == CK_INVALID_HANDLE) {
1754
0
        PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1755
0
        return SECFailure;
1756
0
    }
1757
1758
0
    PK11_SETATTRS(&setTemplate, attrType, (CK_CHAR *)item->data, item->len);
1759
0
    rwsession = PK11_GetRWSession(slot);
1760
0
    if (rwsession == CK_INVALID_HANDLE) {
1761
0
        PORT_SetError(SEC_ERROR_BAD_DATA);
1762
0
        return SECFailure;
1763
0
    }
1764
0
    crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, handle,
1765
0
                                                 &setTemplate, 1);
1766
0
    PK11_RestoreROSession(slot, rwsession);
1767
0
    if (crv != CKR_OK) {
1768
0
        PORT_SetError(PK11_MapError(crv));
1769
0
        return SECFailure;
1770
0
    }
1771
0
    return SECSuccess;
1772
0
}
1773
1774
SECStatus
1775
PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec,
1776
                      CK_ATTRIBUTE_TYPE attrType, SECItem *item)
1777
0
{
1778
0
    PK11SlotInfo *slot = NULL;
1779
0
    CK_OBJECT_HANDLE handle = 0;
1780
1781
0
    handle = PK11_GetObjectHandle(objType, objSpec, &slot);
1782
0
    if (handle == CK_INVALID_HANDLE) {
1783
0
        PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1784
0
        return SECFailure;
1785
0
    }
1786
1787
0
    return PK11_ReadAttribute(slot, handle, attrType, NULL, item);
1788
0
}
1789
1790
SECStatus
1791
PK11_ReadRawAttributes(PLArenaPool *arena, PK11ObjectType objType, void *objSpec,
1792
                       CK_ATTRIBUTE *pTemplate, unsigned int count)
1793
0
{
1794
0
    PK11SlotInfo *slot = NULL;
1795
0
    CK_OBJECT_HANDLE handle = 0;
1796
1797
0
    handle = PK11_GetObjectHandle(objType, objSpec, &slot);
1798
0
    if (handle == CK_INVALID_HANDLE) {
1799
0
        PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
1800
0
        return SECFailure;
1801
0
    }
1802
0
    CK_RV crv = PK11_GetAttributes(arena, slot, handle, pTemplate, count);
1803
0
    if (crv != CKR_OK) {
1804
0
        PORT_SetError(PK11_MapError(crv));
1805
0
        return SECFailure;
1806
0
    }
1807
0
    return SECSuccess;
1808
0
}
1809
1810
/*
1811
 * return the object handle that matches the template
1812
 */
1813
CK_OBJECT_HANDLE
1814
pk11_FindObjectByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *theTemplate, size_t tsize)
1815
19.0k
{
1816
19.0k
    CK_OBJECT_HANDLE object;
1817
19.0k
    CK_RV crv = CKR_SESSION_HANDLE_INVALID;
1818
19.0k
    CK_ULONG objectCount;
1819
1820
    /*
1821
     * issue the find
1822
     */
1823
19.0k
    PK11_EnterSlotMonitor(slot);
1824
19.0k
    if (slot->session != CK_INVALID_HANDLE) {
1825
19.0k
        crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
1826
19.0k
                                                   theTemplate, tsize);
1827
19.0k
    }
1828
19.0k
    if (crv != CKR_OK) {
1829
0
        PK11_ExitSlotMonitor(slot);
1830
0
        PORT_SetError(PK11_MapError(crv));
1831
0
        return CK_INVALID_HANDLE;
1832
0
    }
1833
1834
19.0k
    crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, &object, 1, &objectCount);
1835
19.0k
    PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
1836
19.0k
    PK11_ExitSlotMonitor(slot);
1837
19.0k
    if ((crv != CKR_OK) || (objectCount < 1)) {
1838
        /* shouldn't use SSL_ERROR... here */
1839
19.0k
        PORT_SetError(crv != CKR_OK ? PK11_MapError(crv) : SSL_ERROR_NO_CERTIFICATE);
1840
19.0k
        return CK_INVALID_HANDLE;
1841
19.0k
    }
1842
1843
    /* blow up if the PKCS #11 module returns us and invalid object handle */
1844
0
    PORT_Assert(object != CK_INVALID_HANDLE);
1845
0
    return object;
1846
19.0k
}
1847
1848
/*
1849
 * return all the object handles that matches the template
1850
 */
1851
CK_OBJECT_HANDLE *
1852
pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
1853
                           size_t templCount, int *object_count)
1854
19.0k
{
1855
19.0k
    CK_OBJECT_HANDLE *objID = NULL;
1856
19.0k
    CK_ULONG returned_count = 0;
1857
19.0k
    PRBool owner = PR_TRUE;
1858
19.0k
    CK_SESSION_HANDLE session;
1859
19.0k
    PRBool haslock = PR_FALSE;
1860
19.0k
    CK_RV crv = CKR_SESSION_HANDLE_INVALID;
1861
1862
19.0k
    session = pk11_GetNewSession(slot, &owner);
1863
19.0k
    haslock = (!owner || !(slot->isThreadSafe));
1864
19.0k
    if (haslock) {
1865
0
        PK11_EnterSlotMonitor(slot);
1866
0
    }
1867
19.0k
    if (session != CK_INVALID_HANDLE) {
1868
19.0k
        crv = PK11_GETTAB(slot)->C_FindObjectsInit(session,
1869
19.0k
                                                   findTemplate, templCount);
1870
19.0k
    }
1871
19.0k
    if (crv != CKR_OK) {
1872
0
        if (haslock)
1873
0
            PK11_ExitSlotMonitor(slot);
1874
0
        pk11_CloseSession(slot, session, owner);
1875
0
        PORT_SetError(PK11_MapError(crv));
1876
0
        *object_count = -1;
1877
0
        return NULL;
1878
0
    }
1879
1880
    /*
1881
     * collect all the Matching Objects
1882
     */
1883
19.0k
    do {
1884
19.0k
        CK_OBJECT_HANDLE *oldObjID = objID;
1885
1886
19.0k
        if (objID == NULL) {
1887
19.0k
            objID = (CK_OBJECT_HANDLE *)PORT_Alloc(sizeof(CK_OBJECT_HANDLE) *
1888
19.0k
                                                   (*object_count + PK11_SEARCH_CHUNKSIZE));
1889
19.0k
        } else {
1890
0
            objID = (CK_OBJECT_HANDLE *)PORT_Realloc(objID,
1891
0
                                                     sizeof(CK_OBJECT_HANDLE) * (*object_count + PK11_SEARCH_CHUNKSIZE));
1892
0
        }
1893
1894
19.0k
        if (objID == NULL) {
1895
0
            if (oldObjID)
1896
0
                PORT_Free(oldObjID);
1897
0
            break;
1898
0
        }
1899
19.0k
        crv = PK11_GETTAB(slot)->C_FindObjects(session,
1900
19.0k
                                               &objID[*object_count], PK11_SEARCH_CHUNKSIZE, &returned_count);
1901
19.0k
        if (crv != CKR_OK) {
1902
0
            PORT_SetError(PK11_MapError(crv));
1903
0
            PORT_Free(objID);
1904
0
            objID = NULL;
1905
0
            break;
1906
0
        }
1907
19.0k
        *object_count += returned_count;
1908
19.0k
    } while (returned_count == PK11_SEARCH_CHUNKSIZE);
1909
1910
19.0k
    PK11_GETTAB(slot)->C_FindObjectsFinal(session);
1911
19.0k
    if (haslock) {
1912
0
        PK11_ExitSlotMonitor(slot);
1913
0
    }
1914
19.0k
    pk11_CloseSession(slot, session, owner);
1915
1916
19.0k
    if (objID && (*object_count == 0)) {
1917
19.0k
        PORT_Free(objID);
1918
19.0k
        return NULL;
1919
19.0k
    }
1920
0
    if (objID == NULL)
1921
0
        *object_count = -1;
1922
0
    return objID;
1923
19.0k
}
1924
1925
SECStatus
1926
PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
1927
                             CERTCertificateList **results)
1928
0
{
1929
0
    if (!slot || !derSubject || !results) {
1930
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1931
0
        return SECFailure;
1932
0
    }
1933
0
    *results = NULL;
1934
1935
    // derSubject->data may be null. If so, derSubject->len must be 0.
1936
0
    if (!derSubject->data && derSubject->len != 0) {
1937
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
1938
0
        return SECFailure;
1939
0
    }
1940
1941
0
    CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509;
1942
0
    CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
1943
0
    CK_ATTRIBUTE subjectTemplate[] = {
1944
0
        { CKA_CERTIFICATE_TYPE, &ckc_x_509, sizeof(ckc_x_509) },
1945
0
        { CKA_CLASS, &cko_certificate, sizeof(cko_certificate) },
1946
0
        { CKA_SUBJECT, derSubject->data, derSubject->len },
1947
0
    };
1948
0
    const size_t templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]);
1949
0
    int handleCount = 0;
1950
0
    CK_OBJECT_HANDLE *handles =
1951
0
        pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount,
1952
0
                                   &handleCount);
1953
0
    if (!handles) {
1954
        // pk11_FindObjectsByTemplate indicates there was an error by setting
1955
        // handleCount to -1 (and it has set an error with PORT_SetError).
1956
0
        if (handleCount == -1) {
1957
0
            return SECFailure;
1958
0
        }
1959
0
        return SECSuccess;
1960
0
    }
1961
0
    PORT_Assert(handleCount > 0);
1962
0
    if (handleCount <= 0) {
1963
0
        PORT_Free(handles);
1964
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1965
0
        return SECFailure;
1966
0
    }
1967
0
    if (handleCount > INT_MAX / sizeof(SECItem)) {
1968
0
        PORT_Free(handles);
1969
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1970
0
        return SECFailure;
1971
0
    }
1972
0
    PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1973
0
    if (!arena) {
1974
0
        PORT_Free(handles);
1975
0
        return SECFailure;
1976
0
    }
1977
0
    CERTCertificateList *rawCertificates =
1978
0
        PORT_ArenaNew(arena, CERTCertificateList);
1979
0
    if (!rawCertificates) {
1980
0
        PORT_Free(handles);
1981
0
        PORT_FreeArena(arena, PR_FALSE);
1982
0
        return SECFailure;
1983
0
    }
1984
0
    rawCertificates->arena = arena;
1985
0
    rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount);
1986
0
    if (!rawCertificates->certs) {
1987
0
        PORT_Free(handles);
1988
0
        PORT_FreeArena(arena, PR_FALSE);
1989
0
        return SECFailure;
1990
0
    }
1991
0
    rawCertificates->len = handleCount;
1992
0
    int handleIndex;
1993
0
    for (handleIndex = 0; handleIndex < handleCount; handleIndex++) {
1994
0
        SECStatus rv =
1995
0
            PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE, arena,
1996
0
                               &rawCertificates->certs[handleIndex]);
1997
0
        if (rv != SECSuccess) {
1998
0
            PORT_Free(handles);
1999
0
            PORT_FreeArena(arena, PR_FALSE);
2000
0
            return SECFailure;
2001
0
        }
2002
0
        if (!rawCertificates->certs[handleIndex].data) {
2003
0
            PORT_Free(handles);
2004
0
            PORT_FreeArena(arena, PR_FALSE);
2005
0
            PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
2006
0
            return SECFailure;
2007
0
        }
2008
0
    }
2009
0
    PORT_Free(handles);
2010
0
    *results = rawCertificates;
2011
0
    return SECSuccess;
2012
0
}
2013
2014
/*
2015
 * given a PKCS #11 object, match it's peer based on the KeyID. searchID
2016
 * is typically a privateKey or a certificate while the peer is the opposite
2017
 */
2018
CK_OBJECT_HANDLE
2019
PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
2020
               CK_OBJECT_CLASS matchclass)
2021
0
{
2022
0
    CK_ATTRIBUTE theTemplate[] = {
2023
0
        { CKA_ID, NULL, 0 },
2024
0
        { CKA_CLASS, NULL, 0 }
2025
0
    };
2026
    /* if you change the array, change the variable below as well */
2027
0
    CK_ATTRIBUTE *keyclass = &theTemplate[1];
2028
0
    const size_t tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
2029
    /* if you change the array, change the variable below as well */
2030
0
    CK_OBJECT_HANDLE peerID;
2031
0
    PORTCheapArenaPool tmpArena;
2032
0
    CK_RV crv;
2033
2034
    /* now we need to create space for the public key */
2035
0
    PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
2036
2037
0
    crv = PK11_GetAttributes(&tmpArena.arena, slot, searchID, theTemplate, tsize);
2038
0
    if (crv != CKR_OK) {
2039
0
        PORT_DestroyCheapArena(&tmpArena);
2040
0
        PORT_SetError(PK11_MapError(crv));
2041
0
        return CK_INVALID_HANDLE;
2042
0
    }
2043
2044
0
    if ((theTemplate[0].ulValueLen == 0) || (theTemplate[0].ulValueLen == -1)) {
2045
0
        PORT_DestroyCheapArena(&tmpArena);
2046
0
        if (matchclass == CKO_CERTIFICATE)
2047
0
            PORT_SetError(SEC_ERROR_BAD_KEY);
2048
0
        else
2049
0
            PORT_SetError(SEC_ERROR_NO_KEY);
2050
0
        return CK_INVALID_HANDLE;
2051
0
    }
2052
2053
    /*
2054
     * issue the find
2055
     */
2056
0
    *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass;
2057
2058
0
    peerID = pk11_FindObjectByTemplate(slot, theTemplate, tsize);
2059
0
    PORT_DestroyCheapArena(&tmpArena);
2060
2061
0
    return peerID;
2062
0
}
2063
2064
/*
2065
 * count the number of objects that match the template.
2066
 */
2067
int
2068
PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
2069
                      int templCount)
2070
0
{
2071
0
    CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE];
2072
0
    int object_count = 0;
2073
0
    CK_ULONG returned_count = 0;
2074
0
    CK_RV crv = CKR_SESSION_HANDLE_INVALID;
2075
2076
0
    PK11_EnterSlotMonitor(slot);
2077
0
    if (slot->session != CK_INVALID_HANDLE) {
2078
0
        crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
2079
0
                                                   findTemplate, templCount);
2080
0
    }
2081
0
    if (crv != CKR_OK) {
2082
0
        PK11_ExitSlotMonitor(slot);
2083
0
        PORT_SetError(PK11_MapError(crv));
2084
0
        return object_count;
2085
0
    }
2086
2087
    /*
2088
     * collect all the Matching Objects
2089
     */
2090
0
    do {
2091
0
        crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, objID,
2092
0
                                               PK11_SEARCH_CHUNKSIZE,
2093
0
                                               &returned_count);
2094
0
        if (crv != CKR_OK) {
2095
0
            PORT_SetError(PK11_MapError(crv));
2096
0
            break;
2097
0
        }
2098
0
        object_count += returned_count;
2099
0
    } while (returned_count == PK11_SEARCH_CHUNKSIZE);
2100
2101
0
    PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
2102
0
    PK11_ExitSlotMonitor(slot);
2103
0
    return object_count;
2104
0
}
2105
2106
/*
2107
 * Traverse all the objects in a given slot.
2108
 */
2109
SECStatus
2110
PK11_TraverseSlot(PK11SlotInfo *slot, void *arg)
2111
0
{
2112
0
    int i;
2113
0
    CK_OBJECT_HANDLE *objID = NULL;
2114
0
    int object_count = 0;
2115
0
    pk11TraverseSlot *slotcb = (pk11TraverseSlot *)arg;
2116
2117
0
    objID = pk11_FindObjectsByTemplate(slot, slotcb->findTemplate,
2118
0
                                       slotcb->templateCount, &object_count);
2119
2120
    /*Actually this isn't a failure... there just were no objs to be found*/
2121
0
    if (object_count == 0) {
2122
0
        return SECSuccess;
2123
0
    }
2124
2125
0
    if (objID == NULL) {
2126
0
        return SECFailure;
2127
0
    }
2128
2129
0
    for (i = 0; i < object_count; i++) {
2130
0
        (*slotcb->callback)(slot, objID[i], slotcb->callbackArg);
2131
0
    }
2132
0
    PORT_Free(objID);
2133
0
    return SECSuccess;
2134
0
}
2135
2136
/*
2137
 * Traverse all the objects in all slots.
2138
 */
2139
SECStatus
2140
pk11_TraverseAllSlots(SECStatus (*callback)(PK11SlotInfo *, void *),
2141
                      void *arg, PRBool forceLogin, void *wincx)
2142
0
{
2143
0
    PK11SlotList *list;
2144
0
    PK11SlotListElement *le;
2145
0
    SECStatus rv;
2146
2147
    /* get them all! */
2148
0
    list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, wincx);
2149
0
    if (list == NULL)
2150
0
        return SECFailure;
2151
2152
    /* look at each slot and authenticate as necessary */
2153
0
    for (le = list->head; le; le = le->next) {
2154
0
        if (forceLogin) {
2155
0
            rv = pk11_AuthenticateUnfriendly(le->slot, PR_FALSE, wincx);
2156
0
            if (rv != SECSuccess) {
2157
0
                continue;
2158
0
            }
2159
0
        }
2160
0
        if (callback) {
2161
0
            (*callback)(le->slot, arg);
2162
0
        }
2163
0
    }
2164
2165
0
    PK11_FreeSlotList(list);
2166
2167
0
    return SECSuccess;
2168
0
}
2169
2170
CK_OBJECT_HANDLE *
2171
PK11_FindObjectsFromNickname(char *nickname, PK11SlotInfo **slotptr,
2172
                             CK_OBJECT_CLASS objclass, int *returnCount, void *wincx)
2173
0
{
2174
0
    char *tokenName;
2175
0
    char *delimit;
2176
0
    PK11SlotInfo *slot;
2177
0
    CK_OBJECT_HANDLE *objID;
2178
0
    CK_ATTRIBUTE findTemplate[] = {
2179
0
        { CKA_LABEL, NULL, 0 },
2180
0
        { CKA_CLASS, NULL, 0 },
2181
0
    };
2182
0
    const size_t findCount = sizeof(findTemplate) / sizeof(findTemplate[0]);
2183
0
    SECStatus rv;
2184
0
    PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass));
2185
2186
0
    *slotptr = slot = NULL;
2187
0
    *returnCount = 0;
2188
    /* first find the slot associated with this nickname */
2189
0
    if ((delimit = PORT_Strchr(nickname, ':')) != NULL) {
2190
0
        int len = delimit - nickname;
2191
0
        tokenName = (char *)PORT_Alloc(len + 1);
2192
0
        if (!tokenName) {
2193
0
            return CK_INVALID_HANDLE;
2194
0
        }
2195
0
        PORT_Memcpy(tokenName, nickname, len);
2196
0
        tokenName[len] = 0;
2197
2198
0
        slot = *slotptr = PK11_FindSlotByName(tokenName);
2199
0
        PORT_Free(tokenName);
2200
        /* if we couldn't find a slot, assume the nickname is an internal cert
2201
         * with no proceding slot name */
2202
0
        if (slot == NULL) {
2203
0
            slot = *slotptr = PK11_GetInternalKeySlot();
2204
0
        } else {
2205
0
            nickname = delimit + 1;
2206
0
        }
2207
0
    } else {
2208
0
        *slotptr = slot = PK11_GetInternalKeySlot();
2209
0
    }
2210
0
    if (slot == NULL) {
2211
0
        return CK_INVALID_HANDLE;
2212
0
    }
2213
2214
0
    rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
2215
0
    if (rv != SECSuccess) {
2216
0
        PK11_FreeSlot(slot);
2217
0
        *slotptr = NULL;
2218
0
        return CK_INVALID_HANDLE;
2219
0
    }
2220
2221
0
    findTemplate[0].pValue = nickname;
2222
0
    findTemplate[0].ulValueLen = PORT_Strlen(nickname);
2223
0
    objID = pk11_FindObjectsByTemplate(slot, findTemplate, findCount, returnCount);
2224
0
    if (objID == NULL) {
2225
        /* PKCS #11 isn't clear on whether or not the NULL is
2226
         * stored in the template.... try the find again with the
2227
         * full null terminated string. */
2228
0
        findTemplate[0].ulValueLen += 1;
2229
0
        objID = pk11_FindObjectsByTemplate(slot, findTemplate, findCount,
2230
0
                                           returnCount);
2231
0
        if (objID == NULL) {
2232
            /* Well that's the best we can do. It's just not here */
2233
            /* what about faked nicknames? */
2234
0
            PK11_FreeSlot(slot);
2235
0
            *slotptr = NULL;
2236
0
            *returnCount = 0;
2237
0
        }
2238
0
    }
2239
2240
0
    return objID;
2241
0
}
2242
2243
SECItem *
2244
pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
2245
0
{
2246
0
    CK_ATTRIBUTE theTemplate[] = {
2247
0
        { CKA_ID, NULL, 0 },
2248
0
    };
2249
0
    int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
2250
0
    CK_RV crv;
2251
0
    SECItem *item;
2252
2253
0
    item = SECITEM_AllocItem(NULL, NULL, 0);
2254
2255
0
    if (item == NULL) {
2256
0
        return NULL;
2257
0
    }
2258
2259
0
    crv = PK11_GetAttributes(NULL, slot, handle, theTemplate, tsize);
2260
0
    if (crv != CKR_OK) {
2261
0
        SECITEM_FreeItem(item, PR_TRUE);
2262
0
        PORT_SetError(PK11_MapError(crv));
2263
0
        return NULL;
2264
0
    }
2265
2266
0
    item->data = (unsigned char *)theTemplate[0].pValue;
2267
0
    item->len = theTemplate[0].ulValueLen;
2268
2269
0
    return item;
2270
0
}
2271
2272
PRBool
2273
PK11_ObjectGetFIPSStatus(PK11ObjectType objType, void *objSpec)
2274
0
{
2275
0
    PK11SlotInfo *slot = NULL;
2276
0
    CK_OBJECT_HANDLE handle = 0;
2277
2278
0
    handle = PK11_GetObjectHandle(objType, objSpec, &slot);
2279
0
    if (handle == CK_INVALID_HANDLE) {
2280
0
        PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
2281
0
        return PR_FALSE;
2282
0
    }
2283
0
    return pk11slot_GetFIPSStatus(slot, slot->session, handle,
2284
0
                                  CKT_NSS_OBJECT_CHECK);
2285
0
}