Coverage Report

Created: 2025-06-24 06:49

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