Coverage Report

Created: 2024-11-21 07:03

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