Coverage Report

Created: 2026-10-06 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nss/lib/dev/ckhelper.c
Line
Count
Source
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
#include "pkcs11.h"
6
7
#ifndef DEVM_H
8
#include "devm.h"
9
#endif /* DEVM_H */
10
11
#ifndef CKHELPER_H
12
#include "ckhelper.h"
13
#endif /* CKHELPER_H */
14
15
extern const NSSError NSS_ERROR_DEVICE_ERROR;
16
extern const NSSError NSS_ERROR_INTERNAL_ERROR;
17
18
static const CK_BBOOL s_true = CK_TRUE;
19
NSS_IMPLEMENT_DATA const NSSItem
20
    g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
21
22
static const CK_BBOOL s_false = CK_FALSE;
23
NSS_IMPLEMENT_DATA const NSSItem
24
    g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
25
26
static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
27
NSS_IMPLEMENT_DATA const NSSItem
28
    g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
29
30
static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
31
NSS_IMPLEMENT_DATA const NSSItem
32
    g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
33
34
static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
35
NSS_IMPLEMENT_DATA const NSSItem
36
    g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
37
38
static PRBool
39
is_string_attribute(
40
    CK_ATTRIBUTE_TYPE aType)
41
0
{
42
0
    PRBool isString;
43
0
    switch (aType) {
44
0
        case CKA_LABEL:
45
0
        case CKA_NSS_EMAIL:
46
0
        case CKA_NSS_URL:
47
0
            isString = PR_TRUE;
48
0
            break;
49
0
        default:
50
0
            isString = PR_FALSE;
51
0
            break;
52
0
    }
53
0
    return isString;
54
0
}
55
56
NSS_IMPLEMENT PRStatus
57
nssCKObject_GetAttributes(
58
    CK_OBJECT_HANDLE object,
59
    CK_ATTRIBUTE_PTR obj_template,
60
    CK_ULONG count,
61
    NSSArena *arenaOpt,
62
    nssSession *session,
63
    NSSSlot *slot)
64
0
{
65
0
    nssArenaMark *mark = NULL;
66
0
    CK_SESSION_HANDLE hSession;
67
0
    CK_ULONG i = 0;
68
0
    CK_RV ckrv;
69
0
    PRStatus nssrv;
70
0
    PRBool alloced = PR_FALSE;
71
0
    void *epv = nssSlot_GetCryptokiEPV(slot);
72
0
    hSession = session->handle;
73
0
    if (arenaOpt) {
74
0
        mark = nssArena_Mark(arenaOpt);
75
0
        if (!mark) {
76
0
            goto loser;
77
0
        }
78
0
    }
79
0
    nssSession_EnterMonitor(session);
80
    /* XXX kinda hacky, if the storage size is already in the first template
81
     * item, then skip the alloc portion
82
     */
83
0
    if (obj_template[0].ulValueLen == 0) {
84
        /* Get the storage size needed for each attribute */
85
0
        ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
86
0
                                               object, obj_template, count);
87
0
        if (ckrv != CKR_OK &&
88
0
            ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
89
0
            ckrv != CKR_ATTRIBUTE_SENSITIVE) {
90
0
            nssSession_ExitMonitor(session);
91
0
            nss_SetError(NSS_ERROR_DEVICE_ERROR);
92
0
            goto loser;
93
0
        }
94
        /* Allocate memory for each attribute. */
95
0
        for (i = 0; i < count; i++) {
96
0
            CK_ULONG ulValueLen = obj_template[i].ulValueLen;
97
0
            if (ulValueLen == 0 || ulValueLen >= (CK_ULONG)PR_UINT32_MAX) {
98
0
                obj_template[i].pValue = NULL;
99
0
                obj_template[i].ulValueLen = 0;
100
0
                continue;
101
0
            }
102
0
            if (is_string_attribute(obj_template[i].type)) {
103
0
                ulValueLen++;
104
0
            }
105
0
            obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
106
0
            if (!obj_template[i].pValue) {
107
0
                nssSession_ExitMonitor(session);
108
0
                goto loser;
109
0
            }
110
0
        }
111
0
        alloced = PR_TRUE;
112
0
    }
113
    /* Obtain the actual attribute values. */
114
0
    ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
115
0
                                           object, obj_template, count);
116
0
    nssSession_ExitMonitor(session);
117
0
    if (ckrv != CKR_OK &&
118
0
        ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
119
0
        ckrv != CKR_ATTRIBUTE_SENSITIVE) {
120
0
        nss_SetError(NSS_ERROR_DEVICE_ERROR);
121
0
        goto loser;
122
0
    }
123
0
    if (alloced && arenaOpt) {
124
0
        nssrv = nssArena_Unmark(arenaOpt, mark);
125
0
        if (nssrv != PR_SUCCESS) {
126
0
            goto loser;
127
0
        }
128
0
    }
129
130
0
    if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
131
0
                      (ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
132
        /* old tokens would keep the length of '0' and not deal with any
133
         * of the attributes we passed. For those tokens read them one at
134
         * a time */
135
0
        for (i = 0; i < count; i++) {
136
0
            if ((obj_template[i].ulValueLen == 0) ||
137
0
                (obj_template[i].ulValueLen == -1)) {
138
0
                obj_template[i].ulValueLen = 0;
139
0
                (void)nssCKObject_GetAttributes(object, &obj_template[i], 1,
140
0
                                                arenaOpt, session, slot);
141
0
            }
142
0
        }
143
0
    }
144
0
    return PR_SUCCESS;
145
0
loser:
146
0
    if (alloced) {
147
0
        if (arenaOpt) {
148
            /* release all arena memory allocated before the failure. */
149
0
            (void)nssArena_Release(arenaOpt, mark);
150
0
        } else {
151
0
            CK_ULONG j;
152
            /* free each heap object that was allocated before the failure. */
153
0
            for (j = 0; j < i; j++) {
154
0
                nss_ZFreeIf(obj_template[j].pValue);
155
0
            }
156
0
        }
157
0
    }
158
0
    return PR_FAILURE;
159
0
}
160
161
NSS_IMPLEMENT PRStatus
162
nssCKObject_GetAttributeItem(
163
    CK_OBJECT_HANDLE object,
164
    CK_ATTRIBUTE_TYPE attribute,
165
    NSSArena *arenaOpt,
166
    nssSession *session,
167
    NSSSlot *slot,
168
    NSSItem *rvItem)
169
0
{
170
0
    CK_ATTRIBUTE attr = { 0, NULL, 0 };
171
0
    PRStatus nssrv;
172
0
    attr.type = attribute;
173
0
    nssrv = nssCKObject_GetAttributes(object, &attr, 1,
174
0
                                      arenaOpt, session, slot);
175
0
    if (nssrv != PR_SUCCESS) {
176
0
        return nssrv;
177
0
    }
178
0
    rvItem->data = (void *)attr.pValue;
179
0
    rvItem->size = (PRUint32)attr.ulValueLen;
180
0
    return PR_SUCCESS;
181
0
}
182
183
NSS_IMPLEMENT PRBool
184
nssCKObject_IsAttributeTrue(
185
    CK_OBJECT_HANDLE object,
186
    CK_ATTRIBUTE_TYPE attribute,
187
    nssSession *session,
188
    NSSSlot *slot,
189
    PRStatus *rvStatus)
190
0
{
191
0
    CK_BBOOL bool;
192
0
    CK_ATTRIBUTE_PTR attr;
193
0
    CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
194
0
    CK_RV ckrv;
195
0
    void *epv = nssSlot_GetCryptokiEPV(slot);
196
0
    attr = &atemplate;
197
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
198
0
    nssSession_EnterMonitor(session);
199
0
    ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object,
200
0
                                           &atemplate, 1);
201
0
    nssSession_ExitMonitor(session);
202
0
    if (ckrv != CKR_OK) {
203
0
        *rvStatus = PR_FAILURE;
204
0
        return PR_FALSE;
205
0
    }
206
0
    *rvStatus = PR_SUCCESS;
207
0
    return (PRBool)(bool == CK_TRUE);
208
0
}
209
210
NSS_IMPLEMENT PRStatus
211
nssCKObject_SetAttributes(
212
    CK_OBJECT_HANDLE object,
213
    CK_ATTRIBUTE_PTR obj_template,
214
    CK_ULONG count,
215
    nssSession *session,
216
    NSSSlot *slot)
217
0
{
218
0
    CK_RV ckrv;
219
0
    void *epv = nssSlot_GetCryptokiEPV(slot);
220
0
    nssSession_EnterMonitor(session);
221
0
    ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object,
222
0
                                           obj_template, count);
223
0
    nssSession_ExitMonitor(session);
224
0
    if (ckrv == CKR_OK) {
225
0
        return PR_SUCCESS;
226
0
    } else {
227
0
        return PR_FAILURE;
228
0
    }
229
0
}
230
231
NSS_IMPLEMENT PRBool
232
nssCKObject_IsTokenObjectTemplate(
233
    CK_ATTRIBUTE_PTR objectTemplate,
234
    CK_ULONG otsize)
235
0
{
236
0
    CK_ULONG ul;
237
0
    for (ul = 0; ul < otsize; ul++) {
238
0
        if (objectTemplate[ul].type == CKA_TOKEN) {
239
0
            return (*((CK_BBOOL *)objectTemplate[ul].pValue) == CK_TRUE);
240
0
        }
241
0
    }
242
0
    return PR_FALSE;
243
0
}
244
245
static NSSCertificateType
246
nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
247
0
{
248
0
    CK_CERTIFICATE_TYPE ckCertType;
249
0
    if (!attrib->pValue) {
250
        /* default to PKIX */
251
0
        return NSSCertificateType_PKIX;
252
0
    }
253
    /* The token controls ulValueLen; reject any size that cannot hold a
254
     * full CK_CERTIFICATE_TYPE to avoid an out-of-bounds heap read. */
255
0
    if (attrib->ulValueLen != sizeof(CK_CERTIFICATE_TYPE)) {
256
0
        return NSSCertificateType_Unknown;
257
0
    }
258
0
    ckCertType = *((CK_ULONG *)attrib->pValue);
259
0
    switch (ckCertType) {
260
0
        case CKC_X_509:
261
0
            return NSSCertificateType_PKIX;
262
0
        default:
263
0
            break;
264
0
    }
265
0
    return NSSCertificateType_Unknown;
266
0
}
267
268
/* incoming pointers must be valid */
269
NSS_IMPLEMENT PRStatus
270
nssCryptokiCertificate_GetAttributes(
271
    nssCryptokiObject *certObject,
272
    nssSession *sessionOpt,
273
    NSSArena *arenaOpt,
274
    NSSCertificateType *certTypeOpt,
275
    NSSItem *idOpt,
276
    NSSDER *encodingOpt,
277
    NSSDER *issuerOpt,
278
    NSSDER *serialOpt,
279
    NSSDER *subjectOpt)
280
0
{
281
0
    PRStatus status;
282
0
    PRUint32 i;
283
0
    nssSession *session;
284
0
    NSSSlot *slot;
285
0
    CK_ULONG template_size;
286
0
    CK_ATTRIBUTE_PTR attr;
287
0
    CK_ATTRIBUTE cert_template[6];
288
    /* Set up a template of all options chosen by caller */
289
0
    NSS_CK_TEMPLATE_START(cert_template, attr, template_size);
290
0
    if (certTypeOpt) {
291
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE);
292
0
    }
293
0
    if (idOpt) {
294
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
295
0
    }
296
0
    if (encodingOpt) {
297
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
298
0
    }
299
0
    if (issuerOpt) {
300
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER);
301
0
    }
302
0
    if (serialOpt) {
303
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER);
304
0
    }
305
0
    if (subjectOpt) {
306
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
307
0
    }
308
0
    NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size);
309
0
    if (template_size == 0) {
310
        /* caller didn't want anything */
311
0
        return PR_SUCCESS;
312
0
    }
313
314
0
    status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
315
0
                                                certObject, CKO_CERTIFICATE,
316
0
                                                cert_template, template_size);
317
0
    if (status != PR_SUCCESS) {
318
319
0
        session = sessionOpt ? sessionOpt
320
0
                             : nssToken_GetDefaultSession(certObject->token);
321
0
        if (!session) {
322
0
            nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
323
0
            return PR_FAILURE;
324
0
        }
325
326
0
        slot = nssToken_GetSlot(certObject->token);
327
0
        status = nssCKObject_GetAttributes(certObject->handle,
328
0
                                           cert_template, template_size,
329
0
                                           arenaOpt, session, slot);
330
0
        nssSlot_Destroy(slot);
331
0
        if (status != PR_SUCCESS) {
332
0
            return status;
333
0
        }
334
0
    }
335
336
0
    i = 0;
337
0
    if (certTypeOpt) {
338
0
        *certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]);
339
0
        i++;
340
0
    }
341
0
    if (idOpt) {
342
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt);
343
0
        i++;
344
0
    }
345
0
    if (encodingOpt) {
346
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt);
347
0
        i++;
348
0
    }
349
0
    if (issuerOpt) {
350
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt);
351
0
        i++;
352
0
    }
353
0
    if (serialOpt) {
354
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt);
355
0
        i++;
356
0
    }
357
0
    if (subjectOpt) {
358
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt);
359
0
        i++;
360
0
    }
361
0
    return PR_SUCCESS;
362
0
}
363
364
static nssTrustLevel
365
get_nss_trust(
366
    CK_TRUST ckt)
367
0
{
368
0
    nssTrustLevel t;
369
0
    switch (ckt) {
370
0
        case CKT_NSS_NOT_TRUSTED:
371
0
        case CKT_NOT_TRUSTED:
372
0
            t = nssTrustLevel_NotTrusted;
373
0
            break;
374
0
        case CKT_NSS_TRUSTED_DELEGATOR:
375
0
        case CKT_TRUST_ANCHOR:
376
0
            t = nssTrustLevel_TrustedDelegator;
377
0
            break;
378
0
        case CKT_NSS_VALID_DELEGATOR:
379
0
            t = nssTrustLevel_ValidDelegator;
380
0
            break;
381
0
        case CKT_NSS_TRUSTED:
382
0
        case CKT_TRUSTED:
383
0
            t = nssTrustLevel_Trusted;
384
0
            break;
385
0
        case CKT_NSS_MUST_VERIFY_TRUST:
386
0
        case CKT_TRUST_MUST_VERIFY_TRUST:
387
0
            t = nssTrustLevel_MustVerify;
388
0
            break;
389
0
        case CKT_NSS_TRUST_UNKNOWN:
390
0
        case CKT_TRUST_UNKNOWN:
391
0
        default:
392
0
            t = nssTrustLevel_Unknown;
393
0
            break;
394
0
    }
395
0
    return t;
396
0
}
397
398
NSS_IMPLEMENT PRStatus
399
nssCryptokiTrust_GetAttributes(
400
    nssCryptokiObject *trustObject,
401
    nssSession *sessionOpt,
402
    NSSItem *hash,
403
    CK_MECHANISM_TYPE *hashMech,
404
    nssTrustLevel *serverAuth,
405
    nssTrustLevel *clientAuth,
406
    nssTrustLevel *codeSigning,
407
    nssTrustLevel *emailProtection,
408
    PRBool *stepUpApproved)
409
0
{
410
0
    PRStatus status;
411
0
    NSSSlot *slot;
412
0
    nssSession *session;
413
0
    CK_BBOOL isToken = PR_FALSE;
414
    /* default values if the trust is record does not exist. In the highly
415
     * unlikely case that these change, be sure to update softoken's
416
     * 'sftkdb_isNullTrust()' function */
417
0
    CK_BBOOL stepUp = PR_FALSE;
418
0
    CK_TRUST saTrust = CKT_TRUST_UNKNOWN;
419
0
    CK_TRUST caTrust = CKT_TRUST_UNKNOWN;
420
0
    CK_TRUST epTrust = CKT_TRUST_UNKNOWN;
421
0
    CK_TRUST csTrust = CKT_TRUST_UNKNOWN;
422
0
    CK_ATTRIBUTE_PTR attr;
423
0
    CK_ATTRIBUTE trust_template[7];
424
0
    CK_ATTRIBUTE_PTR hash_attr;
425
0
    CK_ULONG trust_size;
426
427
    /* Use the trust object to find the trust settings */
428
0
    NSS_CK_TEMPLATE_START(trust_template, attr, trust_size);
429
0
    NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken);
430
0
    switch (trustObject->trustType) {
431
0
        case CKO_TRUST:
432
0
            *hashMech = CKM_INVALID_MECHANISM;
433
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_PKCS_TRUST_SERVER_AUTH, saTrust);
434
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_PKCS_TRUST_CLIENT_AUTH, caTrust);
435
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_PKCS_TRUST_EMAIL_PROTECTION, epTrust);
436
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_PKCS_TRUST_CODE_SIGNING, csTrust);
437
0
            hash_attr = attr;
438
0
            NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_HASH_OF_CERTIFICATE, hash);
439
0
            NSS_CK_SET_ATTRIBUTE_FIXED_PTR(attr, CKA_NAME_HASH_ALGORITHM, hashMech);
440
0
            break;
441
0
        case CKO_NSS_TRUST:
442
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_NSS_TRUST_SERVER_AUTH, saTrust);
443
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_NSS_TRUST_CLIENT_AUTH, caTrust);
444
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_NSS_TRUST_EMAIL_PROTECTION, epTrust);
445
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_NSS_TRUST_CODE_SIGNING, csTrust);
446
0
            NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_NSS_TRUST_STEP_UP_APPROVED, stepUp);
447
0
            hash_attr = attr;
448
0
            NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_NSS_CERT_SHA1_HASH, hash);
449
0
            *hashMech = CKM_SHA_1;
450
0
            break;
451
0
        default:
452
            /* shouldn't happen, crash on debug builds if it does */
453
0
            PORT_Assert(0 || trustObject->trustType);
454
0
            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
455
0
            return PR_FAILURE;
456
0
    }
457
0
    NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
458
459
0
    status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
460
0
                                                trustObject,
461
0
                                                trustObject->trustType,
462
0
                                                trust_template, trust_size);
463
0
    if (status != PR_SUCCESS) {
464
0
        session = sessionOpt ? sessionOpt
465
0
                             : nssToken_GetDefaultSession(trustObject->token);
466
0
        if (!session) {
467
0
            nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
468
0
            return PR_FAILURE;
469
0
        }
470
471
0
        slot = nssToken_GetSlot(trustObject->token);
472
0
        status = nssCKObject_GetAttributes(trustObject->handle,
473
0
                                           trust_template, trust_size,
474
0
                                           NULL, session, slot);
475
0
        nssSlot_Destroy(slot);
476
0
        if (status != PR_SUCCESS) {
477
0
            return status;
478
0
        }
479
0
    }
480
481
0
    if (hash_attr->ulValueLen == -1) {
482
        /* The trust object does not have the certificate hash attribute. */
483
0
        hash_attr->ulValueLen = 0;
484
0
    }
485
0
    hash->size = hash_attr->ulValueLen;
486
0
    *serverAuth = get_nss_trust(saTrust);
487
0
    *clientAuth = get_nss_trust(caTrust);
488
0
    *emailProtection = get_nss_trust(epTrust);
489
0
    *codeSigning = get_nss_trust(csTrust);
490
0
    *stepUpApproved = stepUp;
491
0
    return PR_SUCCESS;
492
0
}
493
494
NSS_IMPLEMENT PRStatus
495
nssCryptokiCRL_GetAttributes(
496
    nssCryptokiObject *crlObject,
497
    nssSession *sessionOpt,
498
    NSSArena *arenaOpt,
499
    NSSItem *encodingOpt,
500
    NSSItem *subjectOpt,
501
    CK_ULONG *crl_class,
502
    NSSUTF8 **urlOpt,
503
    PRBool *isKRLOpt)
504
0
{
505
0
    PRStatus status;
506
0
    NSSSlot *slot;
507
0
    nssSession *session;
508
0
    CK_ATTRIBUTE_PTR attr;
509
0
    CK_ATTRIBUTE crl_template[7];
510
0
    CK_ULONG crl_size;
511
0
    PRUint32 i;
512
513
0
    NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
514
0
    if (crl_class) {
515
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
516
0
    }
517
0
    if (encodingOpt) {
518
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
519
0
    }
520
0
    if (urlOpt) {
521
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_URL);
522
0
    }
523
0
    if (isKRLOpt) {
524
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_KRL);
525
0
    }
526
0
    if (subjectOpt) {
527
0
        NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
528
0
    }
529
0
    NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
530
531
0
    status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
532
0
                                                crlObject,
533
0
                                                CKO_NSS_CRL,
534
0
                                                crl_template, crl_size);
535
0
    if (status != PR_SUCCESS) {
536
0
        session = sessionOpt ? sessionOpt
537
0
                             : nssToken_GetDefaultSession(crlObject->token);
538
0
        if (session == NULL) {
539
0
            nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
540
0
            return PR_FAILURE;
541
0
        }
542
543
0
        slot = nssToken_GetSlot(crlObject->token);
544
0
        status = nssCKObject_GetAttributes(crlObject->handle,
545
0
                                           crl_template, crl_size,
546
0
                                           arenaOpt, session, slot);
547
0
        nssSlot_Destroy(slot);
548
0
        if (status != PR_SUCCESS) {
549
0
            return status;
550
0
        }
551
0
    }
552
553
0
    i = 0;
554
0
    if (crl_class) {
555
0
        NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class);
556
0
        i++;
557
0
    }
558
0
    if (encodingOpt) {
559
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt);
560
0
        i++;
561
0
    }
562
0
    if (urlOpt) {
563
0
        NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt);
564
0
        i++;
565
0
    }
566
0
    if (isKRLOpt) {
567
0
        NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt);
568
0
        i++;
569
0
    }
570
0
    if (subjectOpt) {
571
0
        NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt);
572
0
        i++;
573
0
    }
574
0
    return PR_SUCCESS;
575
0
}
576
577
NSS_IMPLEMENT PRStatus
578
nssCryptokiPrivateKey_SetCertificate(
579
    nssCryptokiObject *keyObject,
580
    nssSession *sessionOpt,
581
    const NSSUTF8 *nickname,
582
    NSSItem *id,
583
    NSSDER *subject)
584
0
{
585
0
    CK_RV ckrv;
586
0
    CK_ATTRIBUTE_PTR attr;
587
0
    CK_ATTRIBUTE key_template[3];
588
0
    CK_ULONG key_size;
589
0
    void *epv = nssToken_GetCryptokiEPV(keyObject->token);
590
0
    nssSession *session;
591
0
    NSSToken *token = keyObject->token;
592
0
    nssSession *defaultSession = nssToken_GetDefaultSession(token);
593
0
    PRBool createdSession = PR_FALSE;
594
595
0
    NSS_CK_TEMPLATE_START(key_template, attr, key_size);
596
0
    NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
597
0
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
598
0
    NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
599
0
    NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
600
601
0
    if (sessionOpt) {
602
0
        if (!nssSession_IsReadWrite(sessionOpt)) {
603
0
            return PR_FAILURE;
604
0
        }
605
0
        session = sessionOpt;
606
0
    } else if (defaultSession && nssSession_IsReadWrite(defaultSession)) {
607
0
        session = defaultSession;
608
0
    } else {
609
0
        NSSSlot *slot = nssToken_GetSlot(token);
610
0
        session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
611
0
        nssSlot_Destroy(slot);
612
0
        if (!session) {
613
0
            return PR_FAILURE;
614
0
        }
615
0
        createdSession = PR_TRUE;
616
0
    }
617
618
0
    ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
619
0
                                           keyObject->handle,
620
0
                                           key_template,
621
0
                                           key_size);
622
623
0
    if (createdSession) {
624
0
        nssSession_Destroy(session);
625
0
    }
626
627
0
    return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
628
0
}