Coverage Report

Created: 2024-11-21 07:03

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