Coverage Report

Created: 2025-08-18 06:35

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